diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 5044976a2ebb..08c631347b9f 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -422,6 +422,7 @@ "Current_Chats": "Current Chats", "Current_Status": "Current Status", "Custom": "Custom", + "Custom_agent": "Custom agent", "Custom_Emoji": "Custom Emoji", "Custom_Emoji_Add": "Add New Emoji", "Custom_Emoji_Added_Successfully": "Custom emoji added successfully", @@ -809,6 +810,7 @@ "Iframe_Integration_send_target_origin_Description": "Origin with protocol prefix, which commands are sent to e.g. 'https://localhost', or * to allow sending to anywhere.", "IMAP_intercepter_already_running": "IMAP intercepter already running", "IMAP_intercepter_Not_running": "IMAP intercepter Not running", + "Impersonate_next_agent_from_queue": "Impersonate next agent from queue", "Impersonate_user": "Impersonate User", "Impersonate_user_description": "When enabled, integration posts as the user that triggered integration", "Import": "Import", @@ -1575,6 +1577,7 @@ "Select_a_department": "Select a department", "Select_a_user": "Select a user", "Select_an_avatar": "Select an avatar", + "Select_an_option": "Select an option", "Select_file": "Select file", "Select_role": "Select a Role", "Select_service_to_login": "Select a service to login to load your picture or upload one directly from your computer", diff --git a/packages/rocketchat-livechat/.app/client/lib/chatMessages.js b/packages/rocketchat-livechat/.app/client/lib/chatMessages.js index 664f7df344a8..1209391f61cc 100644 --- a/packages/rocketchat-livechat/.app/client/lib/chatMessages.js +++ b/packages/rocketchat-livechat/.app/client/lib/chatMessages.js @@ -112,7 +112,16 @@ this.ChatMessages = class ChatMessages { }; MsgTyping.stop(rid); - Meteor.call('sendMessageLivechat', msgObject, (error, result) => { + let agent; + const currentAgent = !visitor.roomSubscribed && Livechat.agent; + if (currentAgent) { + agent = { + _id: currentAgent._id, + username: currentAgent.username + }; + } + + Meteor.call('sendMessageLivechat', msgObject, agent, (error, result) => { if (error) { ChatMessage.update(msgObject._id, { $set: { error: true } }); showError(error.reason); diff --git a/packages/rocketchat-livechat/.app/client/lib/triggers.js b/packages/rocketchat-livechat/.app/client/lib/triggers.js index 72f68df99294..3f958c47b97d 100644 --- a/packages/rocketchat-livechat/.app/client/lib/triggers.js +++ b/packages/rocketchat-livechat/.app/client/lib/triggers.js @@ -1,5 +1,44 @@ +/* globals Livechat */ import visitor from '../../imports/client/visitor'; +function getAgent(triggerAction) { + return new Promise((resolve, reject) => { + const { params } = triggerAction; + if (params.sender === 'queue') { + const cache = localStorage.getItem('triggerAgent'); + if (cache) { + const cacheAgent = JSON.parse(cache); + + // cache valid for 1h + if (cacheAgent.ts && Date.now() - cacheAgent.ts < 3600000) { + return resolve(cacheAgent.agent); + } + } + + Meteor.call('livechat:getNextAgent', { + token: visitor.getToken(), + department: Livechat.department + }, (error, result) => { + if (error) { + return reject(error); + } + localStorage.setItem('triggerAgent', JSON.stringify({ + agent: result, + ts: Date.now() + })); + + resolve(result); + }); + } else if (params.sender === 'custom') { + resolve({ + username: params.name + }); + } else { + reject('Unknown sender'); + } + }); +} + this.Triggers = (function() { let triggers = []; let initiated = false; @@ -15,23 +54,27 @@ this.Triggers = (function() { // flag to skip the trigger if the action is 'send-message' trigger.skip = true; - let roomId = visitor.getRoom(); + getAgent(action).then((agent) => { + let roomId = visitor.getRoom(); - if (!roomId) { - roomId = Random.id(); - visitor.setRoom(roomId); - } + if (!roomId) { + roomId = Random.id(); + visitor.setRoom(roomId); + } - Session.set('triggered', true); - ChatMessage.insert({ - msg: action.params.msg, - rid: roomId, - u: { - username: action.params.name + Session.set('triggered', true); + ChatMessage.insert({ + msg: action.params.msg, + rid: roomId, + u: agent + }); + + if (agent._id) { + Livechat.agent = agent; } - }); - parentCall('openWidget'); + parentCall('openWidget'); + }); } }); }; diff --git a/packages/rocketchat-livechat/client/stylesheets/livechat.less b/packages/rocketchat-livechat/client/stylesheets/livechat.less index 6b86af663b38..7d2e34e95075 100644 --- a/packages/rocketchat-livechat/client/stylesheets/livechat.less +++ b/packages/rocketchat-livechat/client/stylesheets/livechat.less @@ -26,9 +26,11 @@ .trigger-value { width: 70%; - input { - display: inline-block !important; + textarea, input, select { + display: block !important; width: auto !important; + margin-bottom: 4px; + min-width: 50%; } } diff --git a/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js b/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js index 651b2367a092..f5360e5468b5 100644 --- a/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js +++ b/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js @@ -56,12 +56,16 @@ Template.livechatTriggersForm.events({ $('.each-action').each(function() { if ($('.trigger-action', this).val() === 'send-message') { + const params = { + sender: $('[name=send-message-sender]', this).val(), + msg: $('[name=send-message-msg]', this).val() + }; + if (params.sender === 'custom') { + params.name = $('[name=send-message-name]', this).val(); + } data.actions.push({ name: $('.trigger-action', this).val(), - params: { - name: $('[name=send-message-name]', this).val(), - msg: $('[name=send-message-msg]', this).val() - } + params }); } else { data.actions.push({ diff --git a/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.html b/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.html index 4a4328b7ae87..9eb80a69147a 100644 --- a/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.html +++ b/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.html @@ -7,8 +7,13 @@
- - + + +
diff --git a/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.js b/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.js index f47ad1c549e2..355f46f54a3f 100644 --- a/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.js +++ b/packages/rocketchat-livechat/client/views/app/triggers/livechatTriggerAction.js @@ -6,6 +6,15 @@ Template.livechatTriggerAction.helpers({ } else if (this.name !== current) { return 'hidden'; } + }, + showCustomName() { + return Template.instance().sender.get() === 'custom' ? '' : 'hidden'; + }, + senderSelected(current) { + return this.params && this.params.sender === current ? true : false; + }, + disableIfGuestPool() { + return RocketChat.settings.get('Livechat_Routing_Method') === 'Guest_Pool'; } }); @@ -13,9 +22,19 @@ Template.livechatTriggerAction.events({ 'change .trigger-action'(e, instance) { instance.$('.trigger-action-value ').addClass('hidden'); instance.$(`.${ e.currentTarget.value }`).removeClass('hidden'); + }, + 'change [name=send-message-sender]'(e, instance) { + instance.sender.set(e.currentTarget.value); } }); Template.livechatTriggerAction.onCreated(function() { this.firstAction = true; + + this.sender = new ReactiveVar(''); + + const data = Template.currentData(); + if (data && data.name === 'send-message') { + this.sender.set(data.params.sender); + } }); diff --git a/packages/rocketchat-livechat/package.js b/packages/rocketchat-livechat/package.js index ea9bbad4675e..79fb59df8fab 100644 --- a/packages/rocketchat-livechat/package.js +++ b/packages/rocketchat-livechat/package.js @@ -148,6 +148,7 @@ Package.onUse(function(api) { api.addFiles('server/methods/getCustomFields.js', 'server'); api.addFiles('server/methods/getAgentData.js', 'server'); api.addFiles('server/methods/getInitialData.js', 'server'); + api.addFiles('server/methods/getNextAgent.js', 'server'); api.addFiles('server/methods/loadHistory.js', 'server'); api.addFiles('server/methods/loginByToken.js', 'server'); api.addFiles('server/methods/pageVisited.js', 'server'); diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js index 4b996733d818..d4f26ccb8789 100644 --- a/packages/rocketchat-livechat/server/lib/Livechat.js +++ b/packages/rocketchat-livechat/server/lib/Livechat.js @@ -61,7 +61,21 @@ RocketChat.Livechat = { return RocketChat.models.Users.findOnlineAgents(); } }, - getRoom(guest, message, roomInfo) { + getRequiredDepartment(onlineRequired = true) { + const departments = RocketChat.models.LivechatDepartment.findEnabledWithAgents(); + + return departments.fetch().find((dept) => { + if (!dept.showOnRegistration) { + return false; + } + if (!onlineRequired) { + return true; + } + const onlineAgents = RocketChat.models.LivechatDepartmentAgents.getOnlineForDepartment(dept._id); + return onlineAgents.count() > 0; + }); + }, + getRoom(guest, message, roomInfo, agent) { let room = RocketChat.models.Rooms.findOneById(message.rid); let newRoom = false; @@ -72,20 +86,17 @@ RocketChat.Livechat = { if (room == null) { // if no department selected verify if there is at least one active and pick the first - if (!guest.department) { - const departments = RocketChat.models.LivechatDepartment.findEnabledWithAgents(); - if (departments.count() > 0) { - departments.forEach((dept) => { - if (!guest.department && dept.showOnRegistration) { - guest.department = dept._id; - } - }); + if (!agent && !guest.department) { + const department = this.getRequiredDepartment(); + + if (department) { + guest.department = department._id; } } // delegate room creation to QueueMethods const routingMethod = RocketChat.settings.get('Livechat_Routing_Method'); - room = RocketChat.QueueMethods[routingMethod](guest, message, roomInfo); + room = RocketChat.QueueMethods[routingMethod](guest, message, roomInfo, agent); newRoom = true; } @@ -96,8 +107,8 @@ RocketChat.Livechat = { return { room, newRoom }; }, - sendMessage({ guest, message, roomInfo }) { - const { room, newRoom } = this.getRoom(guest, message, roomInfo); + sendMessage({ guest, message, roomInfo, agent }) { + const { room, newRoom } = this.getRoom(guest, message, roomInfo, agent); if (guest.name) { message.alias = guest.name; } diff --git a/packages/rocketchat-livechat/server/lib/QueueMethods.js b/packages/rocketchat-livechat/server/lib/QueueMethods.js index 1e4086e98f30..831b4407efa0 100644 --- a/packages/rocketchat-livechat/server/lib/QueueMethods.js +++ b/packages/rocketchat-livechat/server/lib/QueueMethods.js @@ -6,10 +6,12 @@ RocketChat.QueueMethods = { * default method where the agent with the least number * of open chats is paired with the incoming livechat */ - 'Least_Amount'(guest, message, roomInfo) { - const agent = RocketChat.Livechat.getNextAgent(guest.department); + 'Least_Amount'(guest, message, roomInfo, agent) { if (!agent) { - throw new Meteor.Error('no-agent-online', 'Sorry, no online agents'); + agent = RocketChat.Livechat.getNextAgent(guest.department); + if (!agent) { + throw new Meteor.Error('no-agent-online', 'Sorry, no online agents'); + } } const roomCode = RocketChat.models.Rooms.getNextLivechatRoomCode(); diff --git a/packages/rocketchat-livechat/server/methods/getNextAgent.js b/packages/rocketchat-livechat/server/methods/getNextAgent.js new file mode 100644 index 000000000000..a9d09f5c6332 --- /dev/null +++ b/packages/rocketchat-livechat/server/methods/getNextAgent.js @@ -0,0 +1,25 @@ +Meteor.methods({ + 'livechat:getNextAgent'({ token, department }) { + check(token, String); + + const room = RocketChat.models.Rooms.findOpenByVisitorToken(token).fetch(); + + if (room && room.length > 0) { + return; + } + + if (!department) { + const requireDeparment = RocketChat.Livechat.getRequiredDepartment(); + if (requireDeparment) { + department = requireDeparment._id; + } + } + + const agent = RocketChat.Livechat.getNextAgent(department); + if (!agent) { + return; + } + + return RocketChat.models.Users.getAgentInfo(agent.agentId); + } +}); diff --git a/packages/rocketchat-livechat/server/methods/sendMessageLivechat.js b/packages/rocketchat-livechat/server/methods/sendMessageLivechat.js index b112474e4aeb..88a2ff587648 100644 --- a/packages/rocketchat-livechat/server/methods/sendMessageLivechat.js +++ b/packages/rocketchat-livechat/server/methods/sendMessageLivechat.js @@ -1,7 +1,7 @@ import LivechatVisitors from '../models/LivechatVisitors'; Meteor.methods({ - sendMessageLivechat({ token, _id, rid, msg }) { + sendMessageLivechat({ token, _id, rid, msg }, agent) { check(token, String); check(_id, String); check(rid, String); @@ -27,7 +27,8 @@ Meteor.methods({ rid, msg, token - } + }, + agent }); } });