From 2d5d3672985499fa0249823925dd20b4ace2b5fc Mon Sep 17 00:00:00 2001 From: Achilles Rasquinha Date: Tue, 2 Jan 2018 12:50:36 +0530 Subject: [PATCH] chat-fixes --- .../chat/doctype/chat_profile/chat_profile.js | 11 +- .../doctype/chat_profile/chat_profile.json | 43 +++- .../chat/doctype/chat_profile/chat_profile.py | 183 +++++----------- frappe/chat/doctype/chat_room/chat_room.py | 84 +++++--- .../chat_room_user/chat_room_user.json | 10 +- frappe/core/doctype/user/user.json | 63 +----- frappe/core/doctype/user/user.py | 3 - frappe/public/js/frappe/chat.js | 202 ++++++++++-------- socketio.js | 28 +++ 9 files changed, 299 insertions(+), 328 deletions(-) diff --git a/frappe/chat/doctype/chat_profile/chat_profile.js b/frappe/chat/doctype/chat_profile/chat_profile.js index d10c66379e..e59b370c08 100644 --- a/frappe/chat/doctype/chat_profile/chat_profile.js +++ b/frappe/chat/doctype/chat_profile/chat_profile.js @@ -1,8 +1,9 @@ -// Copyright (c) 2017, Frappe Technologies and contributors -// For license information, please see license.txt - +/* eslint semi: "never" */ frappe.ui.form.on('Chat Profile', { - refresh: function(frm) { - + refresh: (form) => { + if ( form.doc.user !== frappe.session.user ) { + form.disable_save(true) + form.set_read_only(true) + } } }); diff --git a/frappe/chat/doctype/chat_profile/chat_profile.json b/frappe/chat/doctype/chat_profile/chat_profile.json index 4a9348bf3a..1918727e1a 100644 --- a/frappe/chat/doctype/chat_profile/chat_profile.json +++ b/frappe/chat/doctype/chat_profile/chat_profile.json @@ -3,7 +3,7 @@ "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, - "autoname": "CP.#####", + "autoname": "field:user", "beta": 1, "creation": "2017-11-13 18:26:57.943027", "custom": 0, @@ -13,6 +13,37 @@ "editable_grid": 1, "engine": "InnoDB", "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "user", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "User", + "length": 0, + "no_copy": 0, + "options": "User", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -40,7 +71,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, "set_only_once": 0, "unique": 0 @@ -234,13 +265,13 @@ "hide_toolbar": 0, "idx": 0, "image_view": 0, - "in_create": 0, + "in_create": 1, "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-12-19 11:23:04.791395", - "modified_by": "achilles@erpnext.com", + "modified": "2018-01-01 18:44:47.226982", + "modified_by": "Administrator", "module": "Chat", "name": "Chat Profile", "name_case": "", @@ -267,7 +298,7 @@ "write": 1 } ], - "quick_entry": 1, + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, "show_name_in_global_search": 0, diff --git a/frappe/chat/doctype/chat_profile/chat_profile.py b/frappe/chat/doctype/chat_profile/chat_profile.py index 55f3ec812b..8078141a1f 100644 --- a/frappe/chat/doctype/chat_profile/chat_profile.py +++ b/frappe/chat/doctype/chat_profile/chat_profile.py @@ -1,13 +1,12 @@ # imports - module imports from frappe.model.document import Document -from frappe import _, _dict # <- the best thing ever happened to frappe +from frappe import _ import frappe # imports - frappe module imports from frappe.core.doctype.version.version import get_diff -from frappe.chat.doctype.chat_room.chat_room import get_user_chat_rooms +from frappe.chat.doctype.chat_room import chat_room from frappe.chat.util import ( - get_user_doc, safe_json_loads, filter_dict, dictify @@ -15,159 +14,81 @@ from frappe.chat.util import ( session = frappe.session -# TODO -# User -# [ ] Deleting a User should also delete its Chat Profile. -# [ ] Ensuring username is mandatory when User has been created. - -# Chat Profile -# [x] Link Chat Profile DocType to User when User has been created. -# [x] Once done, add a validator to check Chat Profile has been -# created only once. -# [x] Users can view other Users Chat Profile, but not update the same. -# Not sure, but circular link would be helpful. - class ChatProfile(Document): - # trigger from DocType def before_save(self): if not self.is_new(): self.get_doc_before_save() def on_update(self): - user = get_user_doc() + if not self.is_new(): + b, a = self.get_doc_before_save(), self + diff = dictify(get_diff(a, b)) + if diff: + user = session.user - if user.chat_profile: - if user.chat_profile != self.name: - frappe.throw(_("Sorry! You don't have permission to update this profile.")) - else: - if not self.is_new(): - before = self.get_doc_before_save() - after = self + fields = [changed[0] for changed in diff.changed] - diff = dictify(get_diff(before, after)) - if diff: - fields = [change[0] for change in diff.changed] + if 'status' in fields: + rooms = chat_room.get(user, filters = ['type', '=', 'Direct']) + update = dict(user = user, data = dict(status = self.status)) - # NOTE: Version DocType is the best thing ever. Selective Updates to Chat Rooms/Users FTW. + for room in rooms: + frappe.publish_realtime('frappe.chat.profile:update', update, room = room.name, after_commit = True) - # status update are dispatched to current user and Direct Chat Rooms. - if 'status' in fields: - # TODO: you can add filters within get_user_chat_rooms - rooms = get_user_chat_rooms(user) - rooms = [r for r in rooms if r.type == 'Direct'] - resp = dict( - user = user.name, - data = dict( - status = self.status - ) - ) +def authenticate(user): + if user != session.user: + frappe.throw(_("Sorry, you're not authorized.")) - for room in rooms: - frappe.publish_realtime('frappe.chat.profile:update', resp, room = room.name, after_commit = True) +@frappe.whitelist() +def get(user, fields = None): + duser = frappe.get_doc('User', user) + dprof = frappe.get_doc('Chat Profile', user) - if 'display_widget' in fields: - resp = dict( - user = user.name, - data = dict( - display_widget = bool(self.display_widget) - ) - ) - frappe.publish_realtime('frappe.chat.profile:update', resp, user = user.name, after_commit = True) + profile = dict( + # User + name = duser.name, + email = duser.email, + first_name = duser.first_name, + last_name = duser.last_name, + username = duser.username, + avatar = duser.user_image, + bio = duser.bio, -def get_user_chat_profile_doc(user = None): - user = get_user_doc(user) - prof = frappe.get_doc('Chat Profile', user.chat_profile) - - return prof - -def get_user_chat_profile(user = None, fields = None): - ''' - Returns the Chat Profile for a given user. - ''' - user = get_user_doc(user) - prof = get_user_chat_profile_doc(user) - - data = dict( - name = user.name, - email = user.email, - first_name = user.first_name, - last_name = user.last_name, - username = user.username, - avatar = user.user_image, - bio = user.bio, - - status = prof.status, - chat_bg = prof.chat_background, - - notification_tones = bool(prof.notification_tones), - conversation_tones = bool(prof.conversation_tones), # frappe, y u no jsonify 0,1 bools? :( - display_widget = bool(prof.display_widget) + # Chat Profile + status = dprof.status, + chat_background = dprof.chat_background, + notification_tones = bool(dprof.notification_tones), + conversation_tones = bool(dprof.conversation_tones), + display_widget = bool(dprof.display_widget) ) + profile = filter_dict(profile, fields) - try: - data = filter_dict(data, fields) - except KeyError as e: - frappe.throw(str(e)) - - return data - -def get_new_chat_profile_doc(user = None, link = True): - user = get_user_doc(user) - prof = frappe.new_doc('Chat Profile') - prof.save() - - if link: - user.update(dict( - chat_profile = prof.name - )) - user.save() - - return prof + return dictify(profile) @frappe.whitelist() def create(user, exists_ok = False, fields = None): - ''' - Creates a Chat Profile for the current session user, throws error if exists. - ''' - exists, fields = safe_json_loads(exists_ok, fields) - user = get_user_doc(user) + authenticate(user) - if user.name != session.user: - frappe.throw(_("Sorry! You don't have permission to create a profile for user {name}.".format( - name = user.name - ))) + exists_ok, fields = safe_json_loads(exists_ok, fields) - if user.chat_profile: - if not exists: - frappe.throw(_("Sorry! You cannot create more than one Chat Profile.")) - - prof = get_user_chat_profile(user, fields) + if frappe.db.exists('Chat Profile', user): + if not exists_ok: + frappe.throw(_('Chat Profile for User {user} exists.'.format(user = user))) else: - prof = get_new_chat_profile_doc(user) - prof = get_user_chat_profile(user, fields) + dprof = frappe.new_doc('Chat Profile') + dprof.user = user + dprof.save() - return dictify(prof) + profile = get(user, fields = fields) -@frappe.whitelist() -def get(user = None, fields = None): - ''' - Returns a user's Chat Profile. - ''' - fields = safe_json_loads(fields) - prof = get_user_chat_profile(user, fields) - - return dictify(prof) + return profile @frappe.whitelist() def update(user, data): + authenticate(user) + data = safe_json_loads(data) - user = get_user_doc(user) - if user.name != session.user: - frappe.throw(_("Sorry! You don't have permission to update Chat Profile for user {name}.".format( - name = user.name - ))) - - prof = get_user_chat_profile_doc(user) - prof.update(data) - prof.save() \ No newline at end of file + dprof = frappe.get_doc('Chat Profile', user) + dprof.update(data) + dprof.save(ignore_permissions = True) \ No newline at end of file diff --git a/frappe/chat/doctype/chat_room/chat_room.py b/frappe/chat/doctype/chat_room/chat_room.py index d30d65fd20..b86cd6deea 100644 --- a/frappe/chat/doctype/chat_room/chat_room.py +++ b/frappe/chat/doctype/chat_room/chat_room.py @@ -2,9 +2,9 @@ import json # imports - module imports -import frappe from frappe.model.document import Document -from frappe import _, _dict +from frappe import _ +import frappe # imports - frappe module imports from frappe.core.doctype.version.version import get_diff @@ -188,7 +188,7 @@ def get_new_chat_room_doc(kind, owner, users = None, name = None): docs.append(doc) room.users = docs - room.save() + room.save(ignore_permissions = True) return room @@ -253,35 +253,9 @@ def get_user_chat_rooms(user = None, rooms = None, fields = None): return rooms -@frappe.whitelist() -def create(kind, owner, users = None, name = None): - users = safe_json_loads(users) - if owner != session.user: - frappe.throw(_("Sorry! You're not authorized to create a Chat Room.")) - room = get_new_chat_room(kind = kind, owner = owner, users = users, name = name) - room = squashify(room) - users = [room.owner] + [u for u in room.users] - for u in users: - frappe.publish_realtime('frappe.chat.room:create', room, - user = u, after_commit = True) - return room - -@frappe.whitelist() -def get(user, rooms = None, fields = None): - rooms = safe_json_loads(rooms) - fields = safe_json_loads(fields) - - user = get_user_doc(user) - - if user.name != frappe.session.user: - frappe.throw(_("You're not authorized to view this room.")) - - data = get_user_chat_rooms(user = user, rooms = rooms, fields = fields) - - return data # Could we move pagination to a config, but how? # One possibility is to add to Chat Profile itself. @@ -293,4 +267,54 @@ def get_history(room, user = None, pagination = 20): mess = squashify(mess) - return dictify(mess) \ No newline at end of file + return dictify(mess) + +def authenticate(user): + if user != session.user: + frappe.throw(_("Sorry, you're not authorized.")) + +@frappe.whitelist() +def get(user, rooms = None, fields = None, filters = None): + authenticate(user) + + rooms, fields, filters = safe_json_loads(rooms, fields, filters) + + data = get_user_chat_rooms(user = user, rooms = rooms, fields = fields) + + return data + +@frappe.whitelist() +def create(kind, owner, users = None, name = None): + authenticate(owner) + + users = safe_json_loads(users) + + room = frappe.new_doc('Chat Room') + room.type = kind + room.owner = owner + dusers = [ ] + + if users: + for user in users: + duser = frappe.new_doc('Chat Room User') + duser.name = user + dusers.append(duser) + + room.users = dusers + room.save(ignore_permissions = True) + + + + + + + + room = get_new_chat_room(kind = kind, owner = owner, users = users, name = name) + room = squashify(room) + + users = [room.owner] + [u for u in room.users] + for u in users: + frappe.publish_realtime('frappe.chat.room:create', room, + user = u, after_commit = True) + + return room \ No newline at end of file diff --git a/frappe/chat/doctype/chat_room_user/chat_room_user.json b/frappe/chat/doctype/chat_room_user/chat_room_user.json index 00cd2499e7..fc485915d0 100644 --- a/frappe/chat/doctype/chat_room_user/chat_room_user.json +++ b/frappe/chat/doctype/chat_room_user/chat_room_user.json @@ -3,6 +3,7 @@ "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, + "autoname": "field:user", "beta": 1, "creation": "2017-11-08 15:24:21.029314", "custom": 0, @@ -38,7 +39,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, "set_only_once": 0, "unique": 0 @@ -49,6 +50,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "default": "0", "fieldname": "is_admin", "fieldtype": "Check", "hidden": 0, @@ -79,12 +81,12 @@ "hide_toolbar": 0, "idx": 0, "image_view": 0, - "in_create": 0, + "in_create": 1, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-11-28 11:50:06.165435", + "modified": "2018-01-02 12:28:45.145823", "modified_by": "achilles@erpnext.com", "module": "Chat", "name": "Chat Room User", @@ -92,7 +94,7 @@ "owner": "Administrator", "permissions": [], "quick_entry": 1, - "read_only": 0, + "read_only": 1, "read_only_onload": 0, "show_name_in_global_search": 0, "sort_field": "modified", diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index 6d6eb6748d..9b7bee4891 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -2048,67 +2048,6 @@ "search_index": 0, "set_only_once": 0, "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "chat_section_break", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Chat", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "chat_profile", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Chat Profile", - "length": 0, - "no_copy": 0, - "options": "Chat Profile", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 } ], "has_web_view": 0, @@ -2124,7 +2063,7 @@ "istable": 0, "max_attachments": 5, "menu_index": 0, - "modified": "2017-11-15 13:01:00.085916", + "modified": "2018-01-01 11:11:40.716211", "modified_by": "Administrator", "module": "Core", "name": "User", diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 5e9d33bc67..edf4c285b4 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -16,9 +16,6 @@ from frappe.limits import get_limits from frappe.website.utils import is_signup_enabled from frappe.utils.background_jobs import enqueue -# imports - frappe.chat -from frappe.chat.doctype.chat_profile.chat_profile import get_user_chat_profile_doc - STANDARD_USERS = ("Guest", "Administrator") class MaxUsersReachedError(frappe.ValidationError): pass diff --git a/frappe/public/js/frappe/chat.js b/frappe/public/js/frappe/chat.js index adc1cc4331..945adcad79 100644 --- a/frappe/public/js/frappe/chat.js +++ b/frappe/public/js/frappe/chat.js @@ -1,4 +1,4 @@ -// frappe Chat +// Frappe Chat // Author - Achilles Rasquinha /* eslint semi: "never" */ @@ -6,66 +6,25 @@ // frappe extensions -// frappe.user extensions +// frappe.model extensions +frappe.provide('frappe.model') /** - * @description Returns the first name of a User. - * - * @param {string} user - User - * - * @returns The first name of the user. + * @description Subscribe to a model for realtime updates. * * @example - * frappe.user.first_name("Rahul Malhotra") - * // returns "Rahul" + * frappe.model.subscribe('User') + * // Subscribe to all User records + * + * frappe.model.subscribe('User', 'achilles@frappe.io') + * frappe.model.subscribe('User', ['achilles@frappe.io', 'rushabh@frappe.io']) + * // Subscribe to User of name(s) + * + * frappe.model.subscribe('User', 'achilles@frappe.io', 'username') + * frappe.model.subscribe('User', ['achilles@frappe.io', 'rushabh@frappe.io'], ['email', 'username']) + * // Subscribe to User of name for field(s) */ -frappe.provide('frappe.user') -frappe.user.first_name = user => frappe.user.full_name(user).split(" ")[0] - -// frappe.ui extensions -frappe.provide('frappe.ui') -frappe.ui.Uploader = class -{ - constructor (wrapper, options = { }) - { - this.options = frappe.ui.Uploader.OPTIONS - this.set_wrapper(wrapper) - this.set_options(options) - } - - set_wrapper (wrapper) - { - this.$wrapper = $(wrapper) - - return this - } - - set_options (options) - { - this.options = { ...this.options, ...options } - - return this - } - - render ( ) - { - const $template = $(frappe.ui.Uploader.TEMPLATE) - this.$wrapper.html($template) - } -} -frappe.ui.Uploader.Layout = { DIALOG: 'DIALOG' } -frappe.ui.Uploader.OPTIONS = -{ - layout: frappe.ui.Uploader.Layout.DIALOG -} -frappe.ui.Uploader.TEMPLATE = -` -
- FooBar -
-` - -frappe.provide('frappe.ui.keycode') -frappe.ui.keycode = { RETURN: 13 } +frappe.model.subscribe = (doctype, name, field) => + frappe.realtime.publish('frappe.model:subscribe', { doctype: doctype, name: name, field: field }) /** * @description The base class for all Frappe Errors. @@ -208,6 +167,8 @@ frappe.datetime.compare = (a, b) => // frappe's utility namespace. frappe.provide('frappe._') +frappe._.head = arr => frappe._.is_empty(arr) ? undefined : arr[0] + /** * @description Python-inspired format extension for string objects. * @@ -408,9 +369,71 @@ frappe._.is_mobile = () => */ frappe._.compact = array => array.filter(Boolean) +// frappe extensions + +// frappe.user extensions +/** + * @description Returns the first name of a User. + * + * @param {string} user - User + * + * @returns The first name of the user. + * + * @example + * frappe.user.first_name("Rahul Malhotra") + * // returns "Rahul" + */ +frappe.provide('frappe.user') +frappe.user.first_name = user => frappe._.head(frappe.user.full_name(user).split(" ")) + +// frappe.ui extensions +frappe.provide('frappe.ui') +frappe.ui.Uploader = class +{ + constructor (wrapper, options = { }) + { + this.options = frappe.ui.Uploader.OPTIONS + this.set_wrapper(wrapper) + this.set_options(options) + } + + set_wrapper (wrapper) + { + this.$wrapper = $(wrapper) + + return this + } + + set_options (options) + { + this.options = { ...this.options, ...options } + + return this + } + + render ( ) + { + const $template = $(frappe.ui.Uploader.TEMPLATE) + this.$wrapper.html($template) + } +} +frappe.ui.Uploader.Layout = { DIALOG: 'DIALOG' } +frappe.ui.Uploader.OPTIONS = +{ + layout: frappe.ui.Uploader.Layout.DIALOG +} +frappe.ui.Uploader.TEMPLATE = +` +
+ FooBar +
+` + +frappe.provide('frappe.ui.keycode') +frappe.ui.keycode = { RETURN: 13 } + // frappe.loggers - A registry for frappe loggers. frappe.provide('frappe.loggers') - /** * @description Frappe's Logger Class * @@ -497,14 +520,9 @@ frappe.provide('frappe.chat.profile') * @returns {Promise} * * @example - * frappe.chat.profile.create((profile) => - * { - * // do stuff - * }) - * frappe.chat.profile.create("status").then((profile) => - * { - * console.log(profile) // { status: "Online" } - * }) + * frappe.chat.profile.create(console.log) + * + * frappe.chat.profile.create("status").then(console.log) // { status: "Online" } */ frappe.chat.profile.create = (fields, fn) => { @@ -530,6 +548,35 @@ frappe.chat.profile.create = (fields, fn) => }) } +/** + * @description Create a Chat Profile. + * + * @param {string|array} fields - (Optional) fields to be retrieved after creating a Chat Profile. + * @param {function} fn - (Optional) callback with the returned Chat Profile. + * + * @returns {Promise} + * + * @example + * frappe.chat.profile.create(console.log) + * + * frappe.chat.profile.create("status").then(console.log) // { status: "Online" } + */ +frappe.chat.profile.update = (user, update, fn) => +{ + return new Promise(resolve => + { + frappe.call("frappe.chat.doctype.chat_profile.chat_profile.update", + { user: user || frappe.session.user, data: update }, + response => + { + if ( fn ) + fn(response.message) + + resolve(response.message) + }) + }) +} + // frappe.chat.profile.on frappe.provide('frappe.chat.profile.on') @@ -1373,11 +1420,9 @@ class extends Component } make ( ) { - frappe.chat.profile.create([ - "status", "display_widget", "notification_tones", "conversation_tones" - ], profile => + frappe.chat.profile.create(["status", "display_widget", "notification_tones", "conversation_tones"]).then(profile => { - frappe.log.info(`Chat Profile created for User ${frappe.session.user}.`) + frappe.log.info(`Chat Profile created for User ${frappe.session.user} - ${JSON.stringify(profile)}.`) this.set_state({ profile }) frappe.chat.room.get(rooms => @@ -2538,20 +2583,3 @@ class extends Component { // frappe.components.Select.Option props // same as frappe.components.Select. -frappe.chat.profile.update -= -function (user, update, fn) -{ - return new Promise(resolve => - { - frappe.call("frappe.chat.doctype.chat_profile.chat_profile.update", - { user: user || frappe.session.user, data: update }, - response => - { - if ( fn ) - fn(response.message) - - resolve(response.message) - }) - }) -} \ No newline at end of file diff --git a/socketio.js b/socketio.js index 5bdcf283e2..6999205d3a 100644 --- a/socketio.js +++ b/socketio.js @@ -62,6 +62,33 @@ io.on('connection', function (socket) { socket.user = cookie.parse(socket.request.headers.cookie).user_id; socket.files = {}; + // frappe namespace (temporary till webpack comes in, we can then reuse). + const frappe = { }; + frappe._ = { }; + + frappe._.compact = function (arr) { return arr.filter(Boolean) } + + // frappe.model + // Realtime Database Updates FTW! + function get_model_room (doctype, name, field) { + const site = get_site_name(socket) + const room = frappe._.compact([site, doctype, name, field]).join(":") + + return room + } + + socket.on('frappe.model:subscribe', function (params) { + const doctype = params.doctype + const name = params.name + const field = params.field + + const room = get_model_room(doctype, name, field) + + console.log('frappe.model: Subscribing ' + socket.user + ' to room ' + room); + socket.join(room); + }) + // end frappe.model + // frappe.chat socket.on("frappe.chat.room:subscribe", function (rooms) { if (!Array.isArray(rooms)) { @@ -87,6 +114,7 @@ io.on('connection', function (socket) { user: user }); }); + // end frappe.chat request.get(get_url(socket, '/api/method/frappe.async.get_user_info')) .type('form')