Regression: New Livechat methods and processes (#15242)

pull/15333/head^2
Renato Becker 6 years ago committed by Diego Sampaio
parent a9a87c6012
commit 7c798f57e8
  1. 8
      app/livechat/client/views/app/tabbar/visitorEdit.js
  2. 14
      app/livechat/client/views/app/tabbar/visitorInfo.js
  3. 39
      app/livechat/lib/LivechatInquiry.js
  4. 2
      app/livechat/server/api/v1/room.js
  5. 8
      app/livechat/server/config.js
  6. 4
      app/livechat/server/index.js
  7. 86
      app/livechat/server/lib/Helper.js
  8. 16
      app/livechat/server/lib/Livechat.js
  9. 35
      app/livechat/server/lib/RoutingManager.js
  10. 6
      app/livechat/server/lib/routing/AutoSelection.js
  11. 12
      app/livechat/server/lib/routing/ManualSelection.js
  12. 2
      app/livechat/server/publications/livechatAgents.js
  13. 2
      app/livechat/server/publications/livechatManagers.js
  14. 17
      app/livechat/server/publications/livechatRooms.js
  15. 9
      app/livechat/server/startup.js
  16. 16
      app/models/server/models/LivechatRooms.js
  17. 34
      app/models/server/models/Settings.js
  18. 4
      packages/rocketchat-i18n/i18n/en.i18n.json
  19. 2
      packages/rocketchat-i18n/i18n/pt-BR.i18n.json
  20. 1
      server/startup/migrations/index.js
  21. 34
      server/startup/migrations/v155.js

@ -7,7 +7,7 @@ import { t } from '../../../../../utils';
import { hasRole } from '../../../../../authorization';
import { LivechatVisitor } from '../../../collections/LivechatVisitor';
import { LivechatDepartmentAgents } from '../../../collections/LivechatDepartmentAgents';
import { Rooms } from '../../../../../models';
import { LivechatRoom } from '../../../collections/LivechatRoom';
import './visitorEdit.html';
Template.visitorEdit.helpers({
@ -79,9 +79,11 @@ Template.visitorEdit.onCreated(function() {
this.visitor.set(LivechatVisitor.findOne({ _id: Template.currentData().visitorId }));
});
this.autorun(() => {
const room = Rooms.findOne({ _id: Template.currentData().roomId });
const rid = Template.currentData().roomId;
this.subscribe('livechat:rooms', { _id: rid });
this.autorun(() => {
const room = LivechatRoom.findOne({ _id: rid });
this.room.set(room);
this.tags.set((room && room.tags) || []);
});

@ -10,12 +10,13 @@ import moment from 'moment';
import UAParser from 'ua-parser-js';
import { modal } from '../../../../../ui-utils';
import { Rooms, Subscriptions } from '../../../../../models';
import { Subscriptions } from '../../../../../models';
import { settings } from '../../../../../settings';
import { t, handleError, roomTypes } from '../../../../../utils';
import { hasRole, hasAllPermission, hasAtLeastOnePermission } from '../../../../../authorization';
import { LivechatVisitor } from '../../../collections/LivechatVisitor';
import { LivechatDepartment } from '../../../collections/LivechatDepartment';
import { LivechatRoom } from '../../../collections/LivechatRoom';
import './visitorInfo.html';
const isSubscribedToRoom = () => {
@ -50,7 +51,7 @@ Template.visitorInfo.helpers({
},
room() {
return Template.instance().room.get();
return LivechatRoom.findOne({ _id: this.rid });
},
department() {
@ -72,7 +73,7 @@ Template.visitorInfo.helpers({
const data = Template.currentData();
if (data && data.rid) {
const room = Rooms.findOne(data.rid);
const room = LivechatRoom.findOne(data.rid);
if (room) {
livechatData = _.extend(livechatData, room.livechatData);
}
@ -147,7 +148,7 @@ Template.visitorInfo.helpers({
},
roomOpen() {
const room = Template.instance().room.get();
const room = LivechatRoom.findOne({ _id: this.rid });
const uid = Meteor.userId();
return room && room.open && ((room.servedBy && room.servedBy._id === uid) || hasRole(uid, 'livechat-manager'));
},
@ -281,7 +282,6 @@ Template.visitorInfo.onCreated(function() {
this.user = new ReactiveVar();
this.departmentId = new ReactiveVar(null);
this.tags = new ReactiveVar(null);
this.room = new ReactiveVar(null);
this.routingConfig = new ReactiveVar({});
Meteor.call('livechat:getCustomFields', (err, customFields) => {
@ -298,9 +298,9 @@ Template.visitorInfo.onCreated(function() {
});
if (rid) {
this.subscribe('livechat:rooms', { _id: rid });
this.autorun(() => {
const room = Rooms.findOne({ _id: rid });
this.room.set(room);
const room = LivechatRoom.findOne({ _id: rid });
this.visitorId.set(room && room.v && room.v._id);
this.departmentId.set(room && room.departmentId);
this.tags.set(room && room.tags);

@ -18,7 +18,6 @@ if (Meteor.isServer) {
this.tryEnsureIndex({ name: 1 }); // name of the inquiry (client name for now)
this.tryEnsureIndex({ message: 1 }); // message sent by the client
this.tryEnsureIndex({ ts: 1 }); // timestamp
this.tryEnsureIndex({ agents: 1 }); // Id's of the agents who can see the inquiry (handle departments)
this.tryEnsureIndex({ department: 1 });
this.tryEnsureIndex({ status: 1 }); // 'ready', 'queued', 'taken'
}
@ -56,23 +55,6 @@ if (Meteor.isServer) {
});
}
/*
* mark the inquiry as closed
*/
closeByRoomId(roomId, closeInfo) {
return this.update({
rid: roomId,
}, {
$set: {
status: 'closed',
closer: closeInfo.closer,
closedBy: closeInfo.closedBy,
closedAt: closeInfo.closedAt,
'metrics.chatDuration': closeInfo.chatDuration,
},
});
}
/*
* mark inquiry as open
*/
@ -95,20 +77,6 @@ if (Meteor.isServer) {
});
}
/*
* mark inquiry as open and set agents
*/
queueInquiryWithAgents(inquiryId, agentIds) {
return this.update({
_id: inquiryId,
}, {
$set: {
status: 'queued',
agents: agentIds,
},
});
}
changeDepartmentIdByRoomId(rid, department) {
const query = {
rid,
@ -199,6 +167,13 @@ if (Meteor.isServer) {
return collectionObj.aggregate(aggregate).toArray();
}
/*
* remove the inquiry by roomId
*/
removeByRoomId(rid) {
return this.remove({ rid });
}
}
LivechatInquiry = new LivechatInquiryClass();

@ -103,7 +103,7 @@ API.v1.addRoute('livechat/room.transfer', {
// update visited page history to not expire
Messages.keepHistoryForToken(token);
if (!Livechat.transfer(room, guest, { roomId: rid, departmentId: department })) {
if (!Promise.await(Livechat.transfer(room, guest, { roomId: rid, departmentId: department }))) {
return API.v1.failure();
}

@ -362,15 +362,15 @@ Meteor.startup(function() {
i18nLabel: 'RDStation_Token',
});
settings.add('Livechat_Routing_Method', 'Least_Amount', {
settings.add('Livechat_Routing_Method', 'Auto_Selection', {
type: 'select',
group: 'Livechat',
public: true,
section: 'Routing',
values: [
{ key: 'External', i18nLabel: 'External_Service' },
{ key: 'Least_Amount', i18nLabel: 'Least_Amount' },
{ key: 'Guest_Pool', i18nLabel: 'Guest_Pool' },
{ key: 'Auto_Selection', i18nLabel: 'Auto_Selection' },
{ key: 'Manual_Selection', i18nLabel: 'Manual_Selection' },
],
});
@ -388,7 +388,7 @@ Meteor.startup(function() {
section: 'Routing',
i18nLabel: 'Max_number_incoming_livechats_displayed',
i18nDescription: 'Max_number_incoming_livechats_displayed_description',
enableQuery: { _id: 'Livechat_Routing_Method', value: 'Guest_Pool' },
enableQuery: { _id: 'Livechat_Routing_Method', value: 'Manual_Selection' },
});
settings.add('Livechat_show_queue_list_link', false, {

@ -70,8 +70,8 @@ import './lib/QueueManager';
import './lib/OfficeClock';
import './lib/RoutingManager';
import './lib/routing/External';
import './lib/routing/GuestPool';
import './lib/routing/LeastAmount';
import './lib/routing/ManualSelection';
import './lib/routing/AutoSelection';
import './sendMessageBySMS';
import './unclosedLivechats';
import './publications/customFields';

@ -6,6 +6,7 @@ import { Messages, LivechatRooms, Rooms, Subscriptions, Users } from '../../../m
import { LivechatInquiry } from '../../lib/LivechatInquiry';
import { Livechat } from './Livechat';
import { RoutingManager } from './RoutingManager';
import { callbacks } from '../../../callbacks/server';
export const createLivechatRoom = (rid, name, guest, extraData) => {
check(rid, String);
@ -39,7 +40,9 @@ export const createLivechatRoom = (rid, name, guest, extraData) => {
waitingResponse: true,
}, extraData);
return Rooms.insert(room);
const roomId = Rooms.insert(room);
callbacks.run('livechat.newRoom', room);
return roomId;
};
export const createLivechatInquiry = (rid, name, guest, message, initialStatus) => {
@ -146,6 +149,11 @@ export const createLivechatQueueView = () => {
});
};
export const removeAgentFromSubscription = (rid, { _id, username }) => {
Subscriptions.removeByRoomIdAndUserId(rid, _id);
Messages.createUserLeaveWithRoomIdAndUser(rid, { _id, username });
};
export const dispatchAgentDelegated = (rid, agentId) => {
const agent = agentId && Users.getAgentInfo(agentId);
Livechat.stream.emit(rid, {
@ -155,6 +163,10 @@ export const dispatchAgentDelegated = (rid, agentId) => {
};
export const forwardRoomToAgent = async (room, agentId) => {
if (!room || !room.open) {
return false;
}
const user = Users.findOneOnlineAgentById(agentId);
if (!user) {
return false;
@ -166,31 +178,36 @@ export const forwardRoomToAgent = async (room, agentId) => {
throw new Meteor.Error('error-transferring-inquiry');
}
if (oldServedBy && agentId === oldServedBy._id) {
return false;
}
const { username } = user;
const agent = { agentId, username };
// There are some Enterprise features that may interrupt the fowarding process
// Due to that we need to check whether the agent has been changed or not
const roomTaken = await RoutingManager.takeInquiry(inquiry, agent);
if (!roomTaken) {
return false;
}
if (oldServedBy && agent.agentId !== oldServedBy._id) {
// There are some Enterprise features that may interrupt the fowarding process
// Due to that we need to check whether the agent has been changed or not
const room = await RoutingManager.takeInquiry(inquiry, agent);
if (!room) {
return false;
const { servedBy } = roomTaken;
if (servedBy) {
if (oldServedBy && servedBy._id !== oldServedBy._id) {
removeAgentFromSubscription(rid, oldServedBy);
}
const { servedBy } = room;
if (servedBy && servedBy._id !== oldServedBy._id) {
Subscriptions.removeByRoomIdAndUserId(rid, oldServedBy._id);
Messages.createUserLeaveWithRoomIdAndUser(rid, { _id: oldServedBy._id, username: oldServedBy.username });
Messages.createUserJoinWithRoomIdAndUser(rid, { _id: agent.agentId, username });
return true;
}
Messages.createUserJoinWithRoomIdAndUser(rid, { _id: servedBy._id, username: servedBy.username });
}
return false;
return true;
};
export const forwardRoomToDepartment = async (room, guest, departmentId) => {
if (!room || !room.open) {
return false;
}
const { _id: rid, servedBy: oldServedBy } = room;
const inquiry = LivechatInquiry.findOneByRoomId(rid);
@ -205,30 +222,29 @@ export const forwardRoomToDepartment = async (room, guest, departmentId) => {
// Fake the department to forward the inquiry - Case the forward process does not success
// the inquiry will stay in the same original department
inquiry.department = departmentId;
room = await RoutingManager.delegateInquiry(inquiry);
if (!room) {
const roomTaken = await RoutingManager.delegateInquiry(inquiry);
if (!roomTaken) {
return false;
}
const { servedBy } = room;
// if there was an agent assigned to the chat and there is no new agent assigned
// or the new agent is not the same, then the fowarding process successed
if (oldServedBy && (!servedBy || oldServedBy._id !== servedBy._id)) {
Subscriptions.removeByRoomIdAndUserId(rid, oldServedBy._id);
Messages.createUserLeaveWithRoomIdAndUser(rid, { _id: oldServedBy._id, username: oldServedBy.username });
LivechatRooms.changeDepartmentIdByRoomId(rid, departmentId);
LivechatInquiry.changeDepartmentIdByRoomId(rid, departmentId);
// Update the visitor's department
const { token } = guest;
Livechat.setDepartmentForGuest({ token, department: departmentId });
if (servedBy) {
const { _id, username } = servedBy;
Messages.createUserJoinWithRoomIdAndUser(rid, { _id, username });
}
const { servedBy } = roomTaken;
if (oldServedBy && servedBy && oldServedBy._id === servedBy._id) {
return false;
}
if (oldServedBy) {
removeAgentFromSubscription(rid, oldServedBy);
}
return true;
if (servedBy) {
Messages.createUserJoinWithRoomIdAndUser(rid, servedBy);
}
return false;
LivechatRooms.changeDepartmentIdByRoomId(rid, departmentId);
LivechatInquiry.changeDepartmentIdByRoomId(rid, departmentId);
const { token } = guest;
Livechat.setDepartmentForGuest({ token, department: departmentId });
return true;
};

@ -21,6 +21,7 @@ import {
Messages,
Subscriptions,
Settings,
Rooms,
LivechatDepartmentAgents,
LivechatDepartment,
LivechatCustomField,
@ -294,8 +295,9 @@ export const Livechat = {
};
}
LivechatRooms.closeByRoomId(room._id, closeData);
LivechatInquiry.closeByRoomId(room._id, closeData);
const { _id: rid, servedBy } = room;
LivechatRooms.closeByRoomId(rid, closeData);
LivechatInquiry.removeByRoomId(rid);
const message = {
t: 'livechat-close',
@ -304,14 +306,14 @@ export const Livechat = {
};
// Retreive the closed room
room = LivechatRooms.findOneByIdOrName(room._id);
room = LivechatRooms.findOneByIdOrName(rid);
sendMessage(user, message, room);
if (room.servedBy) {
Subscriptions.hideByRoomIdAndUserId(room._id, room.servedBy._id);
if (servedBy) {
Subscriptions.hideByRoomIdAndUserId(rid, servedBy._id);
}
Messages.createCommandWithRoomIdAndUser('promptTranscript', room._id, closeData.closedBy);
Messages.createCommandWithRoomIdAndUser('promptTranscript', rid, closeData.closedBy);
Meteor.defer(() => {
callbacks.run('livechat.closeRoom', room);
@ -388,7 +390,7 @@ export const Livechat = {
});
if (!_.isEmpty(guestData.name)) {
return LivechatRooms.setNameById(roomData._id, guestData.name, guestData.name) && Subscriptions.updateDisplayNameByRoomId(roomData._id, guestData.name);
return Rooms.setFnameById(roomData._id, guestData.name) && Subscriptions.updateDisplayNameByRoomId(roomData._id, guestData.name);
}
},

@ -2,9 +2,14 @@ import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';
import { settings } from '../../../settings/server';
import { createLivechatSubscription, dispatchAgentDelegated, forwardRoomToAgent, forwardRoomToDepartment } from './Helper';
import { createLivechatSubscription,
dispatchAgentDelegated,
forwardRoomToAgent,
forwardRoomToDepartment,
removeAgentFromSubscription,
} from './Helper';
import { callbacks } from '../../../callbacks/server';
import { LivechatRooms, Rooms, Messages, Subscriptions, Users } from '../../../models/server';
import { LivechatRooms, Rooms, Messages, Users } from '../../../models/server';
import { LivechatInquiry } from '../../lib/LivechatInquiry';
export const RoutingManager = {
@ -68,16 +73,11 @@ export const RoutingManager = {
unassignAgent(inquiry, departmentId) {
const { _id, rid, department } = inquiry;
const room = LivechatRooms.findOneById(rid);
const { servedBy } = room;
if (!servedBy) {
if (!room || !room.open) {
return false;
}
Subscriptions.removeByRoomId(rid);
LivechatRooms.removeAgentByRoomId(rid);
LivechatInquiry.queueInquiry(_id);
if (departmentId && departmentId !== department) {
LivechatRooms.changeDepartmentIdByRoomId(rid, departmentId);
LivechatInquiry.changeDepartmentIdByRoomId(rid, departmentId);
@ -85,15 +85,19 @@ export const RoutingManager = {
inquiry.department = departmentId;
}
this.getMethod().delegateAgent(null, inquiry);
Messages.createUserLeaveWithRoomIdAndUser(rid, { _id: servedBy._id, username: servedBy.username });
dispatchAgentDelegated(rid, null);
const { servedBy } = room;
if (servedBy) {
removeAgentFromSubscription(rid, servedBy);
LivechatRooms.removeAgentByRoomId(rid);
dispatchAgentDelegated(rid, null);
}
LivechatInquiry.queueInquiry(_id);
this.getMethod().delegateAgent(null, inquiry);
return true;
},
async takeInquiry(inquiry, agent) {
// return Room Object
check(agent, Match.ObjectIncluding({
agentId: String,
username: String,
@ -107,7 +111,11 @@ export const RoutingManager = {
const { _id, rid } = inquiry;
const room = LivechatRooms.findOneById(rid);
if (room && room.servedBy && room.servedBy._id === agent.agentId) {
if (!room || !room.open) {
return room;
}
if (room.servedBy && room.servedBy._id === agent.agentId) {
return room;
}
@ -126,7 +134,6 @@ export const RoutingManager = {
async transferRoom(room, guest, transferData) {
const { userId, departmentId } = transferData;
if (userId) {
return forwardRoomToAgent(room, userId);
}

@ -1,12 +1,12 @@
import { RoutingManager } from '../RoutingManager';
import { LivechatDepartmentAgents, Users } from '../../../../models/server';
/* Least Amount Queuing method:
/* Auto Selection Queuing method:
*
* default method where the agent with the least number
* of open chats is paired with the incoming livechat
*/
class LeastAmount {
class AutoSelection {
constructor() {
this.config = {
previewRoom: false,
@ -32,4 +32,4 @@ class LeastAmount {
}
}
RoutingManager.registerMethod('Least_Amount', LeastAmount);
RoutingManager.registerMethod('Auto_Selection', AutoSelection);

@ -7,16 +7,16 @@ import { LivechatInquiry } from '../../../lib/LivechatInquiry';
import { sendNotification } from '../../../../lib/server';
import { LivechatRooms } from '../../../../models/server';
/* Guest Pool Queuing Method:
/* Manual Selection Queuing Method:
*
* An incomming livechat is created as an Inquiry
* which is picked up from an agent.
* An Inquiry is visible to all agents (TODO: in the correct department)
* An Inquiry is visible to all agents
*
* A room is still created with the initial message, but it is occupied by
* only the client until paired with an agent
*/
class GuestPool {
class ManualSelection {
constructor() {
this.config = {
previewRoom: true,
@ -43,9 +43,7 @@ class GuestPool {
// remove agent from room in case the rooms is being transferred or returned to the Queue
LivechatRooms.removeAgentByRoomId(rid);
const agentIds = allAgents.map((agent) => (department ? agent.agentId : agent._id));
LivechatInquiry.queueInquiryWithAgents(inquiry._id, agentIds);
LivechatInquiry.queueInquiry(inquiry._id);
// Alert only the online agents of the queued request
const onlineAgents = Livechat.getOnlineAgents(department);
@ -86,4 +84,4 @@ class GuestPool {
}
}
RoutingManager.registerMethod('Guest_Pool', GuestPool);
RoutingManager.registerMethod('Manual_Selection', ManualSelection);

@ -7,7 +7,7 @@ Meteor.publish('livechat:agents', function() {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:agents' }));
}
if (!hasPermission(this.userId, 'view-l-room')) {
if (!hasPermission(this.userId, 'manage-livechat-agents')) {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:agents' }));
}

@ -7,7 +7,7 @@ Meteor.publish('livechat:managers', function() {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:managers' }));
}
if (!hasPermission(this.userId, 'view-livechat-rooms')) {
if (!hasPermission(this.userId, 'manage-livechat-managers')) {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:managers' }));
}

@ -3,13 +3,25 @@ import { Match, check } from 'meteor/check';
import { hasPermission } from '../../../authorization';
import { LivechatDepartment, LivechatRooms } from '../../../models';
import { canAccessRoom } from '../../../authorization/server/functions/canAccessRoom';
const userCanAccessRoom = ({ _id }) => {
if (!_id) {
return;
}
const room = LivechatRooms.findOneById(_id);
const user = Meteor.user();
return canAccessRoom(room, user);
};
Meteor.publish('livechat:rooms', function(filter = {}, offset = 0, limit = 20) {
if (!this.userId) {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:rooms' }));
}
if (!hasPermission(this.userId, 'view-livechat-rooms')) {
if (!hasPermission(this.userId, 'view-livechat-rooms') && !userCanAccessRoom(filter)) {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:rooms' }));
}
@ -73,7 +85,6 @@ Meteor.publish('livechat:rooms', function(filter = {}, offset = 0, limit = 20) {
}
const self = this;
const handle = LivechatRooms.findLivechat(query, offset, limit).observeChanges({
added(id, fields) {
fields = Object.assign(fields, { lookupDepartment: fields.departmentId ? LivechatDepartment.findOneById(fields.departmentId) : {} });
@ -81,7 +92,7 @@ Meteor.publish('livechat:rooms', function(filter = {}, offset = 0, limit = 20) {
},
changed(id, fields) {
fields = Object.assign(fields, { lookupDepartment: fields.departmentId ? LivechatDepartment.findOneById(fields.departmentId) : {} });
self.added('livechatRoom', id, fields);
self.changed('livechatRoom', id, fields);
},
removed(id) {
self.removed('livechatRoom', id);

@ -18,6 +18,15 @@ Meteor.startup(() => {
return room && room.t === 'l' && user && hasPermission(user._id, 'view-livechat-rooms');
});
addRoomAccessValidator(function(room, user) {
if (!room || !user || room.t !== 'l') {
return;
}
const { _id: userId } = user;
const { servedBy: { _id: agentId } = {} } = room;
return userId === agentId;
});
addRoomAccessValidator(function(room, user, extraData) {
if (!room && extraData && extraData.rid) {
room = LivechatRooms.findOneById(extraData.rid);

@ -430,22 +430,6 @@ export class LivechatRooms extends Base {
this.remove(query);
}
setNameById(_id, name, fname) {
const query = {
_id,
t: 'l',
};
const update = {
$set: {
name,
fname,
},
};
return this.update(query, update);
}
removeById(_id) {
const query = {
_id,

@ -166,6 +166,40 @@ export class Settings extends Base {
return this.update(query, update);
}
addOptionValueById(_id, option = {}) {
const query = {
blocked: { $ne: true },
_id,
};
const { key, i18nLabel } = option;
const update = {
$addToSet: {
values: {
key,
i18nLabel,
},
},
};
return this.update(query, update);
}
removeOptionValueByIdAndKey(_id, key) {
const query = {
blocked: { $ne: true },
_id,
};
const update = {
$pull: {
values: { key },
},
};
return this.update(query, update);
}
// INSERT
createWithIdAndValue(_id, value) {
const record = {

@ -422,6 +422,7 @@
"Automatic_Translation": "Automatic Translation",
"Author_Site": "Author site",
"AutoTranslate": "Auto-Translate",
"Auto_Selection": "Auto Selection",
"Auto_Translate": "Auto-Translate",
"AutoTranslate_APIKey": "API Key",
"AutoTranslate_Change_Language_Description": "Changing the auto-translate language does not translate previous messages.",
@ -1515,7 +1516,6 @@
"Group_favorites": "Group favorites",
"Group_mentions_disabled_x_members": "Group mentions `@all` and `@here` have been disabled for rooms with more than __total__ members.",
"Group_mentions_only": "Group mentions only",
"Guest_Pool": "Guest Pool",
"Hash": "Hash",
"Header": "Header",
"Header_and_Footer": "Header and Footer",
@ -1911,7 +1911,6 @@
"LDAP_Username_Field_Description": "Which field will be used as *username* for new users. Leave empty to use the username informed on login page.<br/>You can use template tags too, like `#{givenName}.#{sn}`.<br/>Default value is `sAMAccountName`.",
"Lead_capture_email_regex": "Lead capture email regex",
"Lead_capture_phone_regex": "Lead capture phone regex",
"Least_Amount": "Least Amount",
"leave-c": "Leave Channels",
"leave-p": "Leave Private Groups",
"Leave": "Leave",
@ -2033,6 +2032,7 @@
"Manager_removed": "Manager removed",
"Managing_assets": "Managing assets",
"Managing_integrations": "Managing integrations",
"Manual_Selection": "Manual Selection",
"Manufacturing": "Manufacturing",
"MapView_Enabled": "Enable Mapview",
"MapView_Enabled_Description": "Enabling mapview will display a location share button on the left of the chat input field.",

@ -388,6 +388,7 @@
"auto-translate": "Traduzir automaticamente",
"auto-translate_description": "Permissão para usar a ferramenta de tradução automática",
"Auto_Load_Images": "Auto Carregar Imagens",
"Auto_Selection": "Auto Seleção",
"AutoLinker": "AutoLinker",
"AutoLinker_Email": "Aplicar para Email",
"AutoLinker_Phone": "Aplicar para Telefone",
@ -1924,6 +1925,7 @@
"Managers": "Gerentes",
"Managing_assets": "Gerenciando recursos",
"Managing_integrations": "Gerenciando integrações",
"Manual_Selection": "Seleção Manual",
"Manufacturing": "Fabricação",
"MapView_Enabled": "Ativar Mapview",
"MapView_Enabled_Description": "A ativação do mapa exibirá um botão de compartilhamento de localização à esquerda do campo de entrada do bate-papo.",

@ -152,4 +152,5 @@ import './v151';
import './v152';
import './v153';
import './v154';
import './v155';
import './xrun';

@ -0,0 +1,34 @@
import { Migrations } from '../../../app/migrations/server';
import { Settings } from '../../../app/models/server';
Migrations.add({
version: 155,
up() {
const _id = 'Livechat_Routing_Method';
const setting = Settings.findOne({ _id });
if (setting) {
const { value } = setting;
let newValue;
switch (value) {
case 'Least_Amount':
newValue = 'Auto_Selection';
break;
case 'Guest_Pool':
newValue = 'Manual_Selection';
break;
}
if (!newValue) {
return;
}
Settings.update({ _id }, {
$set: {
value: newValue,
packageValue: newValue,
},
});
}
},
});
Loading…
Cancel
Save