Skip to content

Commit

Permalink
Merge pull request #9107 from RocketChat/livechat-add-impersonate-opt…
Browse files Browse the repository at this point in the history
…ion-to-triggers

[NEW] Add impersonate option for livechat triggers
  • Loading branch information
sampaiodiego authored Dec 27, 2017
2 parents 02b6b79 + 35aeedb commit 3a0fe1f
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 39 deletions.
3 changes: 3 additions & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
11 changes: 10 additions & 1 deletion packages/rocketchat-livechat/.app/client/lib/chatMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
69 changes: 56 additions & 13 deletions packages/rocketchat-livechat/.app/client/lib/triggers.js
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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');
});
}
});
};
Expand Down
6 changes: 4 additions & 2 deletions packages/rocketchat-livechat/client/stylesheets/livechat.less
Original file line number Diff line number Diff line change
Expand Up @@ -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%;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
</div>
<div class="trigger-value">
<div class="send-message {{hiddenValue 'send-message'}}">
<input type="text" name="send-message-name" placeholder="{{_ "Name_of_agent"}}" value="{{params.name}}" size="15">
<input type="text" name="send-message-msg" placeholder="{{_ "Message"}}" value="{{params.msg}}">
<select name="send-message-sender">
<option value="">{{_ "Select_an_option"}}</option>
<option value="queue" selected="{{senderSelected 'queue'}}" disabled="{{disableIfGuestPool}}">{{_ "Impersonate_next_agent_from_queue"}}</option>
<option value="custom" selected="{{senderSelected 'custom'}}">{{_ "Custom_agent"}}</option>
</select>
<input type="text" name="send-message-name" placeholder="{{_ "Name_of_agent"}}" value="{{params.name}}" class="{{showCustomName}}">
<textarea name="send-message-msg" placeholder="{{_ "Message"}}" rows="3">{{params.msg}}</textarea>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,35 @@ 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';
}
});

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);
}
});
1 change: 1 addition & 0 deletions packages/rocketchat-livechat/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
35 changes: 23 additions & 12 deletions packages/rocketchat-livechat/server/lib/Livechat.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
8 changes: 5 additions & 3 deletions packages/rocketchat-livechat/server/lib/QueueMethods.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
25 changes: 25 additions & 0 deletions packages/rocketchat-livechat/server/methods/getNextAgent.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -27,7 +27,8 @@ Meteor.methods({
rid,
msg,
token
}
},
agent
});
}
});

0 comments on commit 3a0fe1f

Please sign in to comment.