[{{_id}}]
{{_ "Room_Info"}}
-{{_ "Users"}}
--
- {{#each users}}
- {{#unless is_bot}}
+ {{#if users.length}}
+
- + {{username}} - {{email}} + {{#if is_deleted }} ({{_ "Deleted"}}){{/if}} + + {{/unless}} + {{/each}} +
- - {{username}} - {{email}} - {{#if is_deleted }} ({{_ "Deleted"}}){{/if}} + {{name}} + {{#if is_archived}} ({{_ "Importer_Archived"}}){{/if}} + {{#if is_private}} ({{_ "Private_Group"}}){{/if}} - {{/unless}} - {{/each}} -
{{_ "Users"}}
+-
+ {{#each users}}
+ {{#unless is_bot}}
+
{{_ "Channels"}}
+-
+ {{#each channels}}
{{_ "Channels"}}
--
- {{#each channels}}
-
- - {{name}} - {{#if is_archived}} ({{_ "Importer_Archived"}}){{/if}} - {{#if is_private}} ({{_ "Private_Group"}}){{/if}} - - {{/each}} -
{{_ "Messages"}}: {{message_count}}
'); - RocketChat.models.Subscriptions.findWithSendEmailByRoomId(room._id).forEach((sub) => { - if (sub.disableNotifications) { - delete usersToSendEmail[sub.u._id]; - } else { - switch (sub.emailNotifications) { - case 'all': - usersToSendEmail[sub.u._id] = 'force'; - break; - case 'mentions': - if (usersToSendEmail[sub.u._id]) { - usersToSendEmail[sub.u._id] = 'force'; - } - break; - case 'nothing': - delete usersToSendEmail[sub.u._id]; - break; - case 'default': - break; + const usersToSendEmail = {}; + if (room.t === 'd') { + usersToSendEmail[message.rid.replace(message.u._id, '')] = 'direct'; + } else { + RocketChat.models.Subscriptions.findWithSendEmailByRoomId(room._id).forEach((sub) => { + if (sub.disableNotifications) { + return delete usersToSendEmail[sub.u._id]; } - } - }); + const emailNotifications = sub.emailNotifications; + + if (emailNotifications !== 'nothing') { + const mentionedUser = message.mentions.find((mention) => { + return mention._id === sub.u._id; + }); + + if (emailNotifications === 'mentions' || mentionedUser) { + return usersToSendEmail[sub.u._id] = 'mention'; + } + + if (emailNotifications === 'all') { + return usersToSendEmail[sub.u._id] = 'all'; + } + } + delete usersToSendEmail[sub.u._id]; + }); + } const userIdsToSendEmail = Object.keys(usersToSendEmail); let defaultLink; @@ -114,6 +95,24 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { return; } + let emailSubject; + switch (usersToSendEmail[user._id]) { + case 'all': + emailSubject = TAPi18n.__('Offline_Mention_All_Email', { + user: message.u.username, + room: room.name || room.label + }); + break; + case 'direct': + emailSubject = TAPi18n.__('Offline_DM_Email', { user: message.u.username }); + break; + case 'mention': + emailSubject = TAPi18n.__('Offline_Mention_Email', { + user: message.u.username, + room: room.name + }); + break; + } user.emails.some((email) => { if (email.verified) { email = { diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index f30e58de838..238bfa3ad21 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -22,6 +22,22 @@ function replaceMentionedUsernamesWithFullNames(message, mentions) { return message; } +/** + * This function returns a string ready to be shown in the notification + * + * @param {object} message the message to be parsed + */ +function parseMessageText(message, userId) { + const user = RocketChat.models.Users.findOneById(userId); + const lng = user && user.language || RocketChat.settings.get('language') || 'en'; + + if (!message.msg && message.attachments[0]) { + message.msg = message.attachments[0].image_type ? TAPi18n.__('User_uploaded_image', {lng}) : TAPi18n.__('User_uploaded_file', {lng}); + } + message.msg = RocketChat.callbacks.run('beforeNotifyUser', message.msg); + + return message.msg; +} /** * Send notification to user * @@ -31,7 +47,10 @@ function replaceMentionedUsernamesWithFullNames(message, mentions) { * @param {number} duration Duration of notification */ function notifyUser(userId, user, message, room, duration) { + const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true; + message.msg = parseMessageText(message, userId); + if (UI_Use_Real_Name) { message.msg = replaceMentionedUsernamesWithFullNames(message.msg, message.mentions); } @@ -84,7 +103,8 @@ function getBadgeCount(userId) { }, 0); } -RocketChat.callbacks.add('afterSaveMessage', function(message, room) { +RocketChat.callbacks.add('afterSaveMessage', function(message, room, userId) { + // skips this callback if the message was edited if (message.editedAt) { return message; @@ -129,20 +149,41 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { return (settings[types[type][0]].indexOf(id) === -1 || settings[types[type][1]].indexOf(id) !== -1); } - const notificationPreferencesByRoom = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id); - notificationPreferencesByRoom.forEach(function(subscription) { + // Don't fetch all users if room exceeds max members + const maxMembersForNotification = RocketChat.settings.get('Notifications_Max_Room_Members'); + const disableAllMessageNotifications = room.usernames.length > maxMembersForNotification && maxMembersForNotification !== 0; + const subscriptions = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id, disableAllMessageNotifications); + const userIds = []; + subscriptions.forEach((s) => { + userIds.push(s.u._id); + }); + const userSettings = {}; + RocketChat.models.Users.findUsersByIds(userIds, { fields: { 'settings.preferences.desktopNotifications': 1, 'settings.preferences.mobileNotifications': 1 } }).forEach((user) => { + userSettings[user._id] = user.settings; + }); + + subscriptions.forEach((subscription) => { if (subscription.disableNotifications) { settings.dontNotifyDesktopUsers.push(subscription.u._id); settings.dontNotifyMobileUsers.push(subscription.u._id); } else { - if (subscription.desktopNotifications === 'all') { + const preferences = userSettings[subscription.u._id] ? userSettings[subscription.u._id].preferences || {} : {}; + const userDesktopNotificationPreference = preferences.desktopNotifications !== 'default' ? preferences.desktopNotifications : undefined; + const userMobileNotificationPreference = preferences.mobileNotifications !== 'default' ? preferences.mobileNotifications : undefined; + // Set defaults if they don't exist + const { + desktopNotifications = userDesktopNotificationPreference || RocketChat.settings.get('Desktop_Notifications_Default_Alert'), + mobilePushNotifications = userMobileNotificationPreference || RocketChat.settings.get('Mobile_Notifications_Default_Alert') + } = subscription; + + if (desktopNotifications === 'all' && !disableAllMessageNotifications) { settings.alwaysNotifyDesktopUsers.push(subscription.u._id); - } else if (subscription.desktopNotifications === 'nothing') { + } else if (desktopNotifications === 'nothing') { settings.dontNotifyDesktopUsers.push(subscription.u._id); } - if (subscription.mobilePushNotifications === 'all') { + if (mobilePushNotifications === 'all' && !disableAllMessageNotifications) { settings.alwaysNotifyMobileUsers.push(subscription.u._id); - } else if (subscription.mobilePushNotifications === 'nothing') { + } else if (mobilePushNotifications === 'nothing') { settings.dontNotifyMobileUsers.push(subscription.u._id); } } @@ -161,22 +202,17 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { } }); - let push_message; + let push_message = ' '; //Set variables depending on Push Notification settings if (RocketChat.settings.get('Push_show_message')) { - push_message = message.msg; - } else { - push_message = ' '; + push_message = parseMessageText(message, userId); } - let push_username; - let push_room; + let push_username = ''; + let push_room = ''; if (RocketChat.settings.get('Push_show_username_room')) { push_username = user.username; push_room = `#${ room.name }`; - } else { - push_username = ''; - push_room = ''; } if (room.t == null || room.t === 'd') { diff --git a/packages/rocketchat-lib/server/methods/checkUsernameAvailability.js b/packages/rocketchat-lib/server/methods/checkUsernameAvailability.js new file mode 100644 index 00000000000..4304b06d21a --- /dev/null +++ b/packages/rocketchat-lib/server/methods/checkUsernameAvailability.js @@ -0,0 +1,24 @@ +Meteor.methods({ + checkUsernameAvailability(username) { + check(username, String); + + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'setUsername' }); + } + + const user = Meteor.user(); + + if (user.username && !RocketChat.settings.get('Accounts_AllowUsernameChange')) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setUsername' }); + } + + if (user.username === username) { + return true; + } + return RocketChat.checkUsernameAvailability(username); + } +}); + +RocketChat.RateLimiter.limitMethod('checkUsernameAvailability', 1, 1000, { + userId() { return true; } +}); diff --git a/packages/rocketchat-lib/server/methods/deleteMessage.js b/packages/rocketchat-lib/server/methods/deleteMessage.js index f6954129df1..829c77e45ea 100644 --- a/packages/rocketchat-lib/server/methods/deleteMessage.js +++ b/packages/rocketchat-lib/server/methods/deleteMessage.js @@ -14,7 +14,8 @@ Meteor.methods({ fields: { u: 1, rid: 1, - file: 1 + file: 1, + ts: 1 } }); if (originalMessage == null) { @@ -34,7 +35,7 @@ Meteor.methods({ }); } const blockDeleteInMinutes = RocketChat.settings.get('Message_AllowDeleting_BlockDeleteInMinutes'); - if ((blockDeleteInMinutes != null && blockDeleteInMinutes !== 0) || !(forceDelete)) { + if (blockDeleteInMinutes != null && blockDeleteInMinutes !== 0 && !forceDelete) { if (originalMessage.ts == null) { return; } diff --git a/packages/rocketchat-lib/server/methods/getRoomRoles.js b/packages/rocketchat-lib/server/methods/getRoomRoles.js index 4c7dc6c105f..36d6e39f7f5 100644 --- a/packages/rocketchat-lib/server/methods/getRoomRoles.js +++ b/packages/rocketchat-lib/server/methods/getRoomRoles.js @@ -1,6 +1,5 @@ Meteor.methods({ getRoomRoles(rid) { - check(rid, String); if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) { @@ -20,7 +19,19 @@ Meteor.methods({ } }; + const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true; + const roles = RocketChat.models.Roles.find({ scope: 'Subscriptions', description: { $exists: 1, $ne: '' } }).fetch(); - return RocketChat.models.Subscriptions.findByRoomIdAndRoles(rid, _.pluck(roles, '_id'), options).fetch(); + const subscriptions = RocketChat.models.Subscriptions.findByRoomIdAndRoles(rid, _.pluck(roles, '_id'), options).fetch(); + + if (!UI_Use_Real_Name) { + return subscriptions; + } else { + return subscriptions.map(subscription => { + const user = RocketChat.models.Users.findOneById(subscription.u._id); + subscription.u.name = user && user.name; + return subscription; + }); + } } }); diff --git a/packages/rocketchat-lib/server/methods/restartServer.js b/packages/rocketchat-lib/server/methods/restartServer.js index 100cf528155..41d617d2d43 100644 --- a/packages/rocketchat-lib/server/methods/restartServer.js +++ b/packages/rocketchat-lib/server/methods/restartServer.js @@ -12,11 +12,9 @@ Meteor.methods({ Meteor.setTimeout(() => { console.warn('Call to process.exit() timed out, aborting.'); process.abort(); - } - , 1000); + }, 1000); process.exit(1); - } - , 1000); + }, 1000); return { message: 'The_server_will_restart_in_s_seconds', diff --git a/packages/rocketchat-lib/server/methods/sendMessage.js b/packages/rocketchat-lib/server/methods/sendMessage.js index 2f6e41502fc..698136ba061 100644 --- a/packages/rocketchat-lib/server/methods/sendMessage.js +++ b/packages/rocketchat-lib/server/methods/sendMessage.js @@ -68,14 +68,8 @@ Meteor.methods({ } }); // Limit a user, who does not have the "bot" role, to sending 5 msgs/second -DDPRateLimiter.addRule({ - type: 'method', - name: 'sendMessage', +RocketChat.RateLimiter.limitMethod('sendMessage', 5, 1000, { userId(userId) { - const user = RocketChat.models.Users.findOneById(userId); - if (user == null || !user.roles) { - return true; - } - return user.roles.includes('bot'); + return !RocketChat.authz.hasPermission(userId, 'send-many-messages'); } -}, 5, 1000); +}); diff --git a/packages/rocketchat-lib/server/methods/updateMessage.js b/packages/rocketchat-lib/server/methods/updateMessage.js index d55316ff486..f279bb353d6 100644 --- a/packages/rocketchat-lib/server/methods/updateMessage.js +++ b/packages/rocketchat-lib/server/methods/updateMessage.js @@ -39,12 +39,11 @@ Meteor.methods({ } } - if (originalMessage.attachments) { - if (originalMessage.attachments[0].description !== undefined) { - message.attachments = originalMessage.attachments; - message.attachments[0].description = message.msg; - message.msg = originalMessage.msg; - } + // It is possible to have an empty array as the attachments property, so ensure both things exist + if (originalMessage.attachments && originalMessage.attachments.length > 0 && originalMessage.attachments[0].description !== undefined) { + message.attachments = originalMessage.attachments; + message.attachments[0].description = message.msg; + message.msg = originalMessage.msg; } message.u = originalMessage.u; diff --git a/packages/rocketchat-lib/server/models/Avatars.js b/packages/rocketchat-lib/server/models/Avatars.js index 43c7b6be6af..76d88df19f1 100644 --- a/packages/rocketchat-lib/server/models/Avatars.js +++ b/packages/rocketchat-lib/server/models/Avatars.js @@ -1,7 +1,13 @@ +/* globals InstanceStatus */ + RocketChat.models.Avatars = new class extends RocketChat.models._Base { constructor() { super('avatars'); + this.model.before.insert((userId, doc) => { + doc.instanceId = InstanceStatus.id(); + }); + this.tryEnsureIndex({ name: 1 }); } diff --git a/packages/rocketchat-lib/server/models/Messages.js b/packages/rocketchat-lib/server/models/Messages.js index dabf1893663..7b07df2219a 100644 --- a/packages/rocketchat-lib/server/models/Messages.js +++ b/packages/rocketchat-lib/server/models/Messages.js @@ -545,6 +545,16 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base { return this.createWithTypeRoomIdMessageAndUser('owner-removed', roomId, message, user, extraData); } + createNewLeaderWithRoomIdAndUser(roomId, user, extraData) { + const message = user.username; + return this.createWithTypeRoomIdMessageAndUser('new-leader', roomId, message, user, extraData); + } + + createLeaderRemovedWithRoomIdAndUser(roomId, user, extraData) { + const message = user.username; + return this.createWithTypeRoomIdMessageAndUser('leader-removed', roomId, message, user, extraData); + } + createSubscriptionRoleAddedWithRoomIdAndUser(roomId, user, extraData) { const message = user.username; return this.createWithTypeRoomIdMessageAndUser('subscription-role-added', roomId, message, user, extraData); diff --git a/packages/rocketchat-lib/server/models/Rooms.js b/packages/rocketchat-lib/server/models/Rooms.js index 8af16f5e1a9..6b1f9f7e21f 100644 --- a/packages/rocketchat-lib/server/models/Rooms.js +++ b/packages/rocketchat-lib/server/models/Rooms.js @@ -8,7 +8,7 @@ class ModelRooms extends RocketChat.models._Base { this.tryEnsureIndex({ 't': 1 }); this.tryEnsureIndex({ 'u._id': 1 }); - this.cache.ignoreUpdatedFields.push('msgs', 'lm'); + this.cache.ignoreUpdatedFields = ['msgs', 'lm']; this.cache.ensureIndex(['t', 'name'], 'unique'); this.cache.options = {fields: {usernames: 0}}; } @@ -37,6 +37,21 @@ class ModelRooms extends RocketChat.models._Base { return this.findOne(query, options); } + findOneByNameAndNotId(name, rid) { + const query = { + _id: { $ne: rid }, + name + }; + + return this.findOne(query); + } + + findOneByDisplayName(fname, options) { + const query = {fname}; + + return this.findOne(query, options); + } + findOneByNameAndType(name, type, options) { const query = { name, @@ -238,7 +253,8 @@ class ModelRooms extends RocketChat.models._Base { } }; - return this.find(query, options); + // do not use cache + return this._db.find(query, options); } findByNameAndTypeNotContainingUsername(name, type, username, options) { @@ -250,7 +266,8 @@ class ModelRooms extends RocketChat.models._Base { } }; - return this.find(query, options); + // do not use cache + return this._db.find(query, options); } findByNameStartingAndTypes(name, types, options) { @@ -488,12 +505,13 @@ class ModelRooms extends RocketChat.models._Base { return this.update(query, update); } - setNameById(_id, name) { + setNameById(_id, name, fname) { const query = {_id}; const update = { $set: { - name + name, + fname } }; @@ -717,9 +735,10 @@ class ModelRooms extends RocketChat.models._Base { } // INSERT - createWithTypeNameUserAndUsernames(type, name, user, usernames, extraData) { + createWithTypeNameUserAndUsernames(type, name, fname, user, usernames, extraData) { const room = { name, + fname, t: type, usernames, msgs: 0, diff --git a/packages/rocketchat-lib/server/models/Subscriptions.js b/packages/rocketchat-lib/server/models/Subscriptions.js index 2cd8febf09a..8485a9b2aa8 100644 --- a/packages/rocketchat-lib/server/models/Subscriptions.js +++ b/packages/rocketchat-lib/server/models/Subscriptions.js @@ -241,6 +241,8 @@ class ModelSubscriptions extends RocketChat.models._Base { open: true, alert: false, unread: 0, + userMentions: 0, + groupMentions: 0, ls: new Date } }; @@ -281,13 +283,14 @@ class ModelSubscriptions extends RocketChat.models._Base { return this.update(query, update); } - updateNameAndAlertByRoomId(roomId, name) { + updateNameAndAlertByRoomId(roomId, name, fname) { const query = {rid: roomId}; const update = { $set: { name, + fname, alert: true } }; @@ -336,11 +339,10 @@ class ModelSubscriptions extends RocketChat.models._Base { return this.update(query, update, { multi: true }); } - incUnreadOfDirectForRoomIdExcludingUserId(roomId, userId, inc) { + incUnreadForRoomIdExcludingUserId(roomId, userId, inc) { if (inc == null) { inc = 1; } const query = { rid: roomId, - t: 'd', 'u._id': { $ne: userId } @@ -359,8 +361,7 @@ class ModelSubscriptions extends RocketChat.models._Base { return this.update(query, update, { multi: true }); } - incUnreadForRoomIdExcludingUserId(roomId, userId, inc) { - if (inc == null) { inc = 1; } + incGroupMentionsAndUnreadForRoomIdExcludingUserId(roomId, userId, incGroup = 1, incUnread = 1) { const query = { rid: roomId, 'u._id': { @@ -374,15 +375,15 @@ class ModelSubscriptions extends RocketChat.models._Base { open: true }, $inc: { - unread: inc + unread: incUnread, + groupMentions: incGroup } }; return this.update(query, update, { multi: true }); } - incUnreadForRoomIdAndUserIds(roomId, userIds, inc) { - if (inc == null) { inc = 1; } + incUserMentionsAndUnreadForRoomIdAndUserIds(roomId, userIds, incUser = 1, incUnread = 1) { const query = { rid: roomId, 'u._id': { @@ -396,13 +397,26 @@ class ModelSubscriptions extends RocketChat.models._Base { open: true }, $inc: { - unread: inc + unread: incUnread, + userMentions: incUser } }; return this.update(query, update, { multi: true }); } - + updateUserSubscription(rid, userId) { + const query = { + rid, + 'u._id': userId + }; + const update = { + $set: { + open: true, + lastActivity: new Date + } + }; + return this.update(query, update); + } setAlertForRoomIdExcludingUserId(roomId, userId) { const query = { rid: roomId, @@ -421,7 +435,6 @@ class ModelSubscriptions extends RocketChat.models._Base { open: true } }; - return this.update(query, update, { multi: true }); } @@ -537,13 +550,17 @@ class ModelSubscriptions extends RocketChat.models._Base { open: false, alert: false, unread: 0, + userMentions: 0, + groupMentions: 0, ts: room.ts, rid: room._id, name: room.name, + fname: room.fname, t: room.t, u: { _id: user._id, - username: user.username + username: user.username, + name: user.name } }; diff --git a/packages/rocketchat-lib/server/models/Uploads.js b/packages/rocketchat-lib/server/models/Uploads.js index 3beaec043b8..34d1dc6b9ea 100644 --- a/packages/rocketchat-lib/server/models/Uploads.js +++ b/packages/rocketchat-lib/server/models/Uploads.js @@ -1,7 +1,13 @@ +/* globals InstanceStatus */ + RocketChat.models.Uploads = new class extends RocketChat.models._Base { constructor() { super('uploads'); + this.model.before.insert((userId, doc) => { + doc.instanceId = InstanceStatus.id(); + }); + this.tryEnsureIndex({ 'rid': 1 }); this.tryEnsureIndex({ 'uploadedAt': 1 }); } diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 941416475c6..4f3a627c4bf 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -148,6 +148,9 @@ class ModelUsers extends RocketChat.models._Base { }, { name: termRegex + }, + { + 'emails.address': termRegex } ] }, @@ -157,7 +160,8 @@ class ModelUsers extends RocketChat.models._Base { ] }; - return this.find(query, options); + // do not use cache + return this._db.find(query, options); } findUsersByNameOrUsername(nameOrUsername, options) { @@ -225,6 +229,15 @@ class ModelUsers extends RocketChat.models._Base { return this.find(query, options); } + findUsersByIds(ids, options) { + const query = { + _id: { + $in: ids + } + }; + return this.find(query, options); + } + // UPDATE addImportIds(_id, importIds) { importIds = [].concat(importIds); @@ -315,9 +328,8 @@ class ModelUsers extends RocketChat.models._Base { setCustomFields(_id, fields) { const values = {}; - Object.keys(fields).reduce(key => { - const value = fields[key]; - values[`customFields.${ key }`] = value; + Object.keys(fields).forEach(key => { + values[`customFields.${ key }`] = fields[key]; }); const update = {$set: values}; @@ -493,7 +505,7 @@ class ModelUsers extends RocketChat.models._Base { return this.update({ _id }, update); } -// INSERT + // INSERT create(data) { const user = { createdAt: new Date, @@ -506,12 +518,12 @@ class ModelUsers extends RocketChat.models._Base { } -// REMOVE + // REMOVE removeById(_id) { return this.remove(_id); } -/* + /* Find users to send a message by email if: - he is not online - has a verified email diff --git a/packages/rocketchat-lib/server/publications/settings.js b/packages/rocketchat-lib/server/publications/settings.js index 9b4a1016157..3fb7be96702 100644 --- a/packages/rocketchat-lib/server/publications/settings.js +++ b/packages/rocketchat-lib/server/publications/settings.js @@ -58,7 +58,7 @@ Meteor.methods({ RocketChat.models.Settings.cache.on('changed', function(type, setting) { if (setting['public'] === true) { - RocketChat.Notifications.notifyAllInThisInstance('public-settings-changed', type, _.pick(setting, '_id', 'value')); + RocketChat.Notifications.notifyAllInThisInstance('public-settings-changed', type, _.pick(setting, '_id', 'value', 'properties')); } return RocketChat.Notifications.notifyLoggedInThisInstance('private-settings-changed', type, setting); }); diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index 1671d5185be..325ff3d7e74 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -354,6 +354,38 @@ RocketChat.settings.addGroup('General', function() { type: 'boolean', 'public': true }); + this.add('Unread_Count', 'user_and_group_mentions_only', { + type: 'select', + values: [ + { + key: 'all_messages', + i18nLabel: 'All_messages' + }, { + key: 'user_mentions_only', + i18nLabel: 'User_mentions_only' + }, { + key: 'group_mentions_only', + i18nLabel: 'Group_mentions_only' + }, { + key: 'user_and_group_mentions_only', + i18nLabel: 'User_and_group_mentions_only' + } + ], + 'public': true + }); + this.add('Unread_Count_DM', 'all_messages', { + type: 'select', + values: [ + { + key: 'all_messages', + i18nLabel: 'All_messages' + }, { + key: 'mentions_only', + i18nLabel: 'Mentions_only' + } + ], + 'public': true + }); this.add('CDN_PREFIX', '', { type: 'string', 'public': true @@ -395,11 +427,47 @@ RocketChat.settings.addGroup('General', function() { }); }); this.section('Notifications', function() { - return this.add('Desktop_Notifications_Duration', 0, { + this.add('Desktop_Notifications_Duration', 0, { type: 'int', 'public': true, i18nDescription: 'Desktop_Notification_Durations_Description' }); + + this.add('Desktop_Notifications_Default_Alert', 'mentions', { + type: 'select', + values: [{ + key: 'all', + i18nLabel: 'All_messages' + }, { + key: 'mentions', + i18nLabel: 'Mentions' + }, { + key: 'nothing', + i18nLabel: 'Nothing' + }], + public: true + }); + + this.add('Mobile_Notifications_Default_Alert', 'mentions', { + type: 'select', + values: [{ + key: 'all', + i18nLabel: 'All_messages' + }, { + key: 'mentions', + i18nLabel: 'Mentions' + }, { + key: 'nothing', + i18nLabel: 'Nothing' + }], + public: true + }); + + this.add('Notifications_Max_Room_Members', 100, { + type: 'int', + public: true, + i18nDescription: 'Notifications_Max_Room_Members_Description' + }); }); this.section('REST API', function() { return this.add('API_User_Limit', 500, { @@ -770,6 +838,10 @@ RocketChat.settings.addGroup('Message', function() { type: 'boolean', 'public': true }); + this.add('API_Embed_UserAgent', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36', { + type: 'string', + 'public': true + }); this.add('API_EmbedCacheExpirationDays', 30, { type: 'int', 'public': false @@ -806,6 +878,10 @@ RocketChat.settings.addGroup('Message', function() { 'public': true, i18nDescription: 'Message_TimeAndDateFormat_Description' }); + this.add('Message_QuoteChainLimit', 2, { + type: 'int', + 'public': true + }); this.add('Message_HideType_uj', false, { type: 'boolean', 'public': true @@ -822,6 +898,7 @@ RocketChat.settings.addGroup('Message', function() { type: 'boolean', 'public': true }); + return this.add('Message_HideType_mute_unmute', false, { type: 'boolean', 'public': true @@ -1012,6 +1089,27 @@ RocketChat.settings.addGroup('Layout', function() { type: 'boolean', 'public': true }); + this.add('UI_Click_Direct_Message', false, { + type: 'boolean', + 'public': true + }); + this.add('UI_Unread_Counter_Style', 'Different_Style_For_User_Mentions', { + type: 'select', + values: [ + { + key: 'Same_Style_For_Mentions', + i18nLabel: 'Same_Style_For_Mentions' + }, { + key: 'Different_Style_For_User_Mentions', + i18nLabel: 'Different_Style_For_User_Mentions' + } + ], + 'public': true + }); + this.add('UI_Allow_room_names_with_special_chars', false, { + type: 'boolean', + public: true + }); }); }); diff --git a/packages/rocketchat-lib/startup/defaultRoomTypes.js b/packages/rocketchat-lib/startup/defaultRoomTypes.js index a206f6386fd..1c98e5eec70 100644 --- a/packages/rocketchat-lib/startup/defaultRoomTypes.js +++ b/packages/rocketchat-lib/startup/defaultRoomTypes.js @@ -1,11 +1,41 @@ /* globals openRoom */ -RocketChat.roomTypes.add(null, 0, { - icon: 'icon-star', +RocketChat.roomTypes.add('unread', 10, { + unread: true, + condition() { + const user = Meteor.user(); + const preferences = (user && user.settings && user.settings.preferences && user.settings.preferences) || {}; + return preferences.roomsListExhibitionMode === 'unread'; + }, + label: 'Unread' +}); + +RocketChat.roomTypes.add('f', 20, { + header: 'favorite', + icon: 'star', label: 'Favorites' }); -RocketChat.roomTypes.add('c', 10, { - icon: 'icon-hash', +// activity +RocketChat.roomTypes.add('activity', 30, { + condition() { + const user = Meteor.user(); + const preferences = (user && user.settings && user.settings.preferences && user.settings.preferences) || {}; + return preferences.roomsListExhibitionMode === 'activity'; + }, + label: 'Conversations' +}); + +RocketChat.roomTypes.add('channels', 30, { + label: 'Channels', + condition() { + const user = Meteor.user(); + const preferences = (user && user.settings && user.settings.preferences && user.settings.preferences) || {}; + return ['unread', 'category'].includes(preferences.roomsListExhibitionMode) && preferences.mergeChannels; + } +}); +// public +RocketChat.roomTypes.add('c', 30, { + icon: 'hashtag', label: 'Channels', route: { name: 'channel', @@ -24,11 +54,16 @@ RocketChat.roomTypes.add('c', 10, { }, roomName(roomData) { + if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { + return roomData.fname || roomData.name; + } return roomData.name; }, condition() { - return RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || RocketChat.settings.get('Accounts_AllowAnonymousRead') === true; + const user = Meteor.user(); + const preferences = (user && user.settings && user.settings.preferences && user.settings.preferences) || {}; + return !preferences.roomsListExhibitionMode || ['unread', 'category'].includes(preferences.roomsListExhibitionMode) && !preferences.mergeChannels && (RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || RocketChat.settings.get('Accounts_AllowAnonymousRead') === true); }, showJoinLink(roomId) { @@ -36,8 +71,44 @@ RocketChat.roomTypes.add('c', 10, { } }); -RocketChat.roomTypes.add('d', 20, { - icon: 'icon-at', +// private +RocketChat.roomTypes.add('p', 40, { + icon: 'lock', + label: 'Private_Groups', + route: { + name: 'group', + path: '/group/:name', + action(params) { + return openRoom('p', params.name); + } + }, + + findRoom(identifier) { + const query = { + t: 'p', + name: identifier + }; + return ChatRoom.findOne(query); + }, + + roomName(roomData) { + if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { + return roomData.fname || roomData.name; + } + return roomData.name; + }, + + condition() { + const user = Meteor.user(); + const preferences = (user && user.settings && user.settings.preferences && user.settings.preferences) || {}; + return !preferences.roomsListExhibitionMode || ['unread', 'category'].includes(preferences.roomsListExhibitionMode) && !preferences.mergeChannels && RocketChat.authz.hasAllPermission('view-p-room'); + } +}); + + +// direct +RocketChat.roomTypes.add('d', 50, { + icon: false, label: 'Direct_Messages', route: { name: 'direct', @@ -82,7 +153,9 @@ RocketChat.roomTypes.add('d', 20, { }, condition() { - return RocketChat.authz.hasAtLeastOnePermission(['view-d-room', 'view-joined-room']); + const user = Meteor.user(); + const preferences = (user && user.settings && user.settings.preferences && user.settings.preferences) || {}; + return !preferences.roomsListExhibitionMode || ['unread', 'category'].includes(preferences.roomsListExhibitionMode) && RocketChat.authz.hasAtLeastOnePermission(['view-d-room', 'view-joined-room']); }, getUserStatus(roomId) { @@ -92,31 +165,3 @@ RocketChat.roomTypes.add('d', 20, { return Session.get(`user_${ subscription.name }_status`); } }); - -RocketChat.roomTypes.add('p', 30, { - icon: 'icon-lock', - label: 'Private_Groups', - route: { - name: 'group', - path: '/group/:name', - action(params) { - return openRoom('p', params.name); - } - }, - - findRoom(identifier) { - const query = { - t: 'p', - name: identifier - }; - return ChatRoom.findOne(query); - }, - - roomName(roomData) { - return roomData.name; - }, - - condition() { - return RocketChat.authz.hasAllPermission('view-p-room'); - } -}); diff --git a/packages/rocketchat-livechat/.app/.meteor/.finished-upgraders b/packages/rocketchat-livechat/.app/.meteor/.finished-upgraders index a8020370920..2a56593d3f8 100644 --- a/packages/rocketchat-livechat/.app/.meteor/.finished-upgraders +++ b/packages/rocketchat-livechat/.app/.meteor/.finished-upgraders @@ -15,3 +15,4 @@ notices-for-facebook-graph-api-2 1.4.0-remove-old-dev-bundle-link 1.4.1-add-shell-server-package 1.4.3-split-account-service-packages +1.5-add-dynamic-import-package diff --git a/packages/rocketchat-livechat/.app/.meteor/packages b/packages/rocketchat-livechat/.app/.meteor/packages index b9e32033860..c28486a1e03 100644 --- a/packages/rocketchat-livechat/.app/.meteor/packages +++ b/packages/rocketchat-livechat/.app/.meteor/packages @@ -4,15 +4,15 @@ # 'meteor add' and 'meteor remove' will edit this file for you, # but you can also edit it by hand. -meteor@1.6.1 -webapp@1.3.15 +meteor@1.7.0 +webapp@1.3.17 logging@1.1.17 tracker@1.1.3 deps@1.0.12 session@1.1.7 -ddp@1.2.5 +ddp@1.3.0 livedata@1.0.18 -mongo@1.1.17 +mongo@1.1.19 blaze ui spacebars @@ -31,11 +31,12 @@ underscorestring:underscore.string momentjs:moment mizzao:timesync reactive-var@1.0.11 -accounts-password@1.3.6 +accounts-password@1.4.0 tap:i18n smoral:sweetalert -ecmascript@0.7.3 +ecmascript@0.8.1 es5-shim@4.6.15 standard-minifier-css@1.3.4 -standard-minifier-js@2.0.0 -shell-server@0.2.3 +standard-minifier-js@2.1.1 +shell-server@0.2.4 +dynamic-import@0.1.1 diff --git a/packages/rocketchat-livechat/.app/.meteor/release b/packages/rocketchat-livechat/.app/.meteor/release index fb6f3bc15e2..1e7fc5b564c 100644 --- a/packages/rocketchat-livechat/.app/.meteor/release +++ b/packages/rocketchat-livechat/.app/.meteor/release @@ -1 +1 @@ -METEOR@1.4.4.2 +METEOR@1.5.1 diff --git a/packages/rocketchat-livechat/.app/.meteor/versions b/packages/rocketchat-livechat/.app/.meteor/versions index 5d13dcd9ea3..2f8db3f3b54 100644 --- a/packages/rocketchat-livechat/.app/.meteor/versions +++ b/packages/rocketchat-livechat/.app/.meteor/versions @@ -1,31 +1,34 @@ -accounts-base@1.2.17 -accounts-password@1.3.6 +accounts-base@1.3.1 +accounts-password@1.4.0 aldeed:simple-schema@1.5.3 -allow-deny@1.0.5 -babel-compiler@6.18.2 +allow-deny@1.0.6 +babel-compiler@6.19.4 babel-runtime@1.0.1 base64@1.0.10 binary-heap@1.0.10 blaze@2.3.2 blaze-tools@1.0.10 -boilerplate-generator@1.0.11 +boilerplate-generator@1.1.1 caching-compiler@1.1.9 caching-html-compiler@1.1.2 callback-hook@1.0.10 cfs:http-methods@0.0.32 check@1.2.5 -coffeescript@1.12.3_1 -ddp@1.2.5 -ddp-client@1.3.4 -ddp-common@1.2.8 +coffeescript@1.12.6_1 +ddp@1.3.0 +ddp-client@2.0.0 +ddp-common@1.2.9 ddp-rate-limiter@1.0.7 -ddp-server@1.3.14 +ddp-server@2.0.0 deps@1.0.12 diff-sequence@1.0.7 -ecmascript@0.7.3 -ecmascript-runtime@0.3.15 +dynamic-import@0.1.1 +ecmascript@0.8.2 +ecmascript-runtime@0.4.1 +ecmascript-runtime-client@0.4.3 +ecmascript-runtime-server@0.4.1 ejson@1.0.13 -email@1.2.1 +email@1.2.3 es5-shim@4.6.15 geojson-utils@1.0.10 html-tools@1.0.11 @@ -38,29 +41,29 @@ kadira:flow-router@2.12.1 konecty:nrr@2.0.2 less@2.7.9 livedata@1.0.18 -localstorage@1.0.12 +localstorage@1.1.1 logging@1.1.17 mdg:validation-error@0.5.1 -meteor@1.6.1 +meteor@1.7.1 meteorspark:util@0.2.0 minifier-css@1.2.16 -minifier-js@2.0.0 -minimongo@1.0.23 +minifier-js@2.1.1 +minimongo@1.2.1 mizzao:timesync@0.5.0 -modules@0.8.2 -modules-runtime@0.7.10 +modules@0.9.2 +modules-runtime@0.8.0 momentjs:moment@2.18.1 -mongo@1.1.17 +mongo@1.1.22 mongo-id@1.0.6 -npm-bcrypt@0.9.2 -npm-mongo@2.2.24 +npm-bcrypt@0.9.3 +npm-mongo@2.2.30 observe-sequence@1.0.16 ordered-dict@1.0.9 -promise@0.8.8 +promise@0.8.9 raix:eventemitter@0.1.3 random@1.0.10 rate-limit@1.0.8 -reactive-dict@1.1.8 +reactive-dict@1.1.9 reactive-var@1.0.11 retry@1.0.9 rocketchat:streamer@0.5.0 @@ -68,13 +71,13 @@ routepolicy@1.0.12 service-configuration@1.0.11 session@1.1.7 sha@1.0.9 -shell-server@0.2.3 +shell-server@0.2.4 smoral:sweetalert@1.1.1 spacebars@1.0.15 spacebars-compiler@1.1.2 srp@1.0.10 standard-minifier-css@1.3.4 -standard-minifier-js@2.0.0 +standard-minifier-js@2.1.1 tap:i18n@1.8.2 templating@1.3.2 templating-compiler@1.3.2 @@ -85,5 +88,5 @@ ui@1.0.13 underscore@1.0.10 underscorestring:underscore.string@3.3.4 url@1.1.0 -webapp@1.3.15 +webapp@1.3.17 webapp-hashing@1.0.9 diff --git a/packages/rocketchat-livechat/.app/client/lib/chatMessages.js b/packages/rocketchat-livechat/.app/client/lib/chatMessages.js index 5f9c6e6fb6c..1b1a3c7975f 100644 --- a/packages/rocketchat-livechat/.app/client/lib/chatMessages.js +++ b/packages/rocketchat-livechat/.app/client/lib/chatMessages.js @@ -206,7 +206,7 @@ this.ChatMessages = class ChatMessages { 13, // Enter 20, // Caps lock 16, // Shift - 9, // Tab + 9, // Tab 27, // Escape Key 17, // Control Key 91, // Windows Command Key diff --git a/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js b/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js index 836f9388e48..935312f3f94 100644 --- a/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js +++ b/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js @@ -74,8 +74,8 @@ this.Notifications = new class { unRoom(room, eventName, callback) { return this.streamRoom.removeListener(`${ room }/${ eventName }`, callback); } - unUser(callback) { - return this.streamUser.removeListener(visitor.getId(), callback); + unUser(eventName, callback) { + return this.streamUser.removeListener(`${ visitor.getId() }/${ eventName }`, callback); } }; diff --git a/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js b/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js index 648eb78fd37..8aaf7ef7d5c 100644 --- a/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js +++ b/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js @@ -138,8 +138,7 @@ export const RoomHistoryManager = new class { return instance.atBottom = messages.scrollTop >= (messages.scrollHeight - messages.clientHeight); }); - return setTimeout(() => msgElement.removeClass('highlight') - , 500); + return setTimeout(() => msgElement.removeClass('highlight'), 500); } else { const room = this.getRoom(message.rid); room.isLoading.set(true); @@ -187,8 +186,7 @@ export const RoomHistoryManager = new class { return 500; }); - return setTimeout(() => msgElement.removeClass('highlight') - , 500); + return setTimeout(() => msgElement.removeClass('highlight'), 500); }); if (room.loaded == null) { room.loaded = 0; } room.loaded += result.messages.length; diff --git a/packages/rocketchat-livechat/.app/i18n/ar.i18n.json b/packages/rocketchat-livechat/.app/i18n/ar.i18n.json index 63ff96f74b7..f8393f74f95 100644 --- a/packages/rocketchat-livechat/.app/i18n/ar.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/ar.i18n.json @@ -1,17 +1,31 @@ { "Additional_Feedback": "ملاحظات إضافية", "Appearance": "المظهر", - "Conversation_finished": "المحادثة الانتهاء", + "Are_you_sure_do_you_want_end_this_chat": "هل تُؤكّد إنهاء هذه الدردشة؟", + "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "هل تُؤكّد إنهاء هذه الدردشة وتغيير الفرع؟", + "Cancel": "إلغاء", + "Change": "تغيير", + "Chat_ended": "تم إنهاء الدردشة!", + "Choose_a_new_department": "اختيار فرع جديد", + "Close_menu": "إغلاق القائمة", + "Conversation_finished": "تم إنهاء المحادثة", + "End_chat": "إنهاء الدردشة", "How_friendly_was_the_chat_agent": "كيف ودية وكان وكيل الدردشة؟", "How_knowledgeable_was_the_chat_agent": "معرفة كيف كان وكيل الدردشة؟", "How_responsive_was_the_chat_agent": "كيف تستجيب كان وكيل الدردشة؟", "How_satisfied_were_you_with_this_chat": "ما مدى رضاك مع هذه الدردشة؟", - "Installation": "تركيب", + "Installation": "تنصيب", "New_messages": "رسائل جديدة", + "No": "لا", + "Options": "خيارات", "Please_answer_survey": "يرجى ان نتوقف لحظة للرد على مسح سريع حول هذه الدردشة", + "Please_choose_a_department": "الرجاء اختيار فرع", "Please_fill_name_and_email": "الرجاء إدخال الإسم والبريد الإلكتروني", "Powered_by": "مشغل بواسطة", + "Request_video_chat": "طلب دردشة عبر الفيديو", "Select_a_department": "حدد القسم", + "Switch_department": "تغيير الفرع", + "Department_switched": "تم تغيير الفرع", "Send": "إرسال", "Skip": "تخطي", "Start_Chat": "بدأ الدردشة", @@ -19,11 +33,14 @@ "Survey_instructions": "معدل كل سؤال وفقا لالارتياح الخاص بك، 1 وهذا يعني أنك غير راضي تماما و 5 يعني كنت راضيا تماما.", "Thank_you_for_your_feedback": "شكرا لأفادتك", "Thanks_We_ll_get_back_to_you_soon": "شكر! سوف نعود إليك قريبا.", + "transcript_sent": "تم إرسال رسالة النسخ السماعي", "Type_your_email": "اكتب بريدك الالكتروني", "Type_your_message": "اكتب رسالتك", "Type_your_name": "اكتب اسمك", "User_joined": "العضو انضم", "User_left": "اليسار المستخدم", "We_are_offline_Sorry_for_the_inconvenience": "نحن حاليا. آسف للإزعاج.", + "Yes": "نعم", + "You": "أنت", "You_must_complete_all_fields": "يجب عليك إكمال جميع الحقول" } \ No newline at end of file diff --git a/packages/rocketchat-livechat/.app/i18n/el.i18n.json b/packages/rocketchat-livechat/.app/i18n/el.i18n.json index 724ee91211e..d6cb296fd41 100644 --- a/packages/rocketchat-livechat/.app/i18n/el.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/el.i18n.json @@ -1,13 +1,21 @@ { "Additional_Feedback": "Πρόσθετα Σχόλια", "Appearance": "Εμφάνιση", + "Are_you_sure_do_you_want_end_this_chat": "Είσαι σίγουρος ότι θες να τερματίσεις τη συνομιλία;", + "Cancel": "Ακύρωση", + "Change": "Αλλαγή", + "Chat_ended": "Η συνομιλία τελείωσε!", + "Close_menu": "Κλείσιμο μενού", "Conversation_finished": "Η συνομιλία τελείωσε", + "End_chat": "Τερματισμός συνομιλίας", "How_friendly_was_the_chat_agent": "Πόσο φιλικός ήταν ο εκπρόσωπος μας;", "How_knowledgeable_was_the_chat_agent": "Πώς γνώστης ήταν ο εκπρόσωπος μας;", "How_responsive_was_the_chat_agent": "Πώς ανταποκρίσιμος ήταν ο εκπρόσωπος μας;", "How_satisfied_were_you_with_this_chat": "Πόσο ικανοποιημένοι είστε με αυτήν την συνομιλία;", "Installation": "Εγκατάσταση", "New_messages": "Νέα μηνύματα", + "No": "Όχι", + "Options": "Επιλογές", "Please_answer_survey": "Αφιερώστε λίγο χρόνο για να απαντήσετε σε μια σύντομη έρευνα σχετικά με αυτή τη συνομιλία", "Please_fill_name_and_email": "Παρακαλούμε συμπληρώστε το όνομα και το e-mail", "Powered_by": "Powered by", @@ -19,11 +27,14 @@ "Survey_instructions": "Βαθμολογήστε κάθε ερώτηση, σύμφωνα με την ικανοποίησή σας, 1 που σημαίνει ότι θα είναι εντελώς ανικανοποίητοι και 5 σημαίνει ότι είστε απόλυτα ικανοποιημένοι.", "Thank_you_for_your_feedback": "Ευχαριστούμε για την ανταπόκρισή σας", "Thanks_We_ll_get_back_to_you_soon": "Ευχαριστώ! Θα επικοινωνήσουμε μαζί σας σύντομα.", + "transcript_sent": "Το αντίγραφο της συνομιλίας στάλθηκε", "Type_your_email": "Πληκτρολογήστε το email σας", "Type_your_message": "Πληκτρολογήστε το μήνυμά σας", "Type_your_name": "Πληκτρολογήστε το όνομά σας", "User_joined": "εντάχθηκε χρήστη", "User_left": "αριστερή χρήστη", "We_are_offline_Sorry_for_the_inconvenience": "Είμαστε εκτός σύνδεσης. Συγγνώμη για την ταλαιπωρία.", + "Yes": "Ναι", + "You": "Εσύ", "You_must_complete_all_fields": "Πρέπει να συμπληρώσετε όλα τα πεδία" } \ No newline at end of file diff --git a/packages/rocketchat-livechat/.app/i18n/fi.i18n.json b/packages/rocketchat-livechat/.app/i18n/fi.i18n.json index d9797d678df..9efa433e873 100644 --- a/packages/rocketchat-livechat/.app/i18n/fi.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/fi.i18n.json @@ -2,8 +2,11 @@ "Additional_Feedback": "Lisäpalaute", "Appearance": "Ulkoasu", "Are_you_sure_do_you_want_end_this_chat": "Haluatko lopettaa tämän keskustelun?", + "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Oletko varma että haluat lopettaa tämän keskustelun ja vaihtaa osastoa?", "Cancel": "Peruuta", + "Change": "Muuta", "Chat_ended": "Keskustelu lopetettu!", + "Choose_a_new_department": "Valitse uusi osasto", "Close_menu": "Sulje valikko", "Conversation_finished": "Keskustelu päättynyt", "End_chat": "Lopeta keskustelu", @@ -16,9 +19,12 @@ "No": "Ei", "Options": "Valinnat", "Please_answer_survey": "Käytä hetki vastataksesi pikakyselyyn tästä chatista", + "Please_choose_a_department": "Ole hyvä ja valitse uusi osasto", "Please_fill_name_and_email": "Täytä nimi ja sähköpostiosoite", "Powered_by": "Palvelun tarjoaa", "Select_a_department": "Valitse osasto", + "Switch_department": "Vaihda osastoa", + "Department_switched": "Osasto vaihdettu", "Send": "Lähetä", "Skip": "Ohita", "Start_Chat": "Aloita Chat", diff --git a/packages/rocketchat-livechat/.app/i18n/it.i18n.json b/packages/rocketchat-livechat/.app/i18n/it.i18n.json index f333178ee3e..3070e876bd3 100644 --- a/packages/rocketchat-livechat/.app/i18n/it.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/it.i18n.json @@ -1,43 +1,45 @@ { - "Additional_Feedback": "Feedback aggiuntivi", + "Additional_Feedback": "Feedback Aggiuntivi", "Appearance": "Aspetto", - "Are_you_sure_do_you_want_end_this_chat": "Sei sicuro di voler chiudere questa chat?", - "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Sei sicuro di voler terminare la conversazione e cambiare dipartimento?", - "Cancel": "Cancella", + "Are_you_sure_do_you_want_end_this_chat": "Sei sicuro di voler terminare questa chat?", + "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Sei sicuro di voler terminare la chat e cambiare dipartimento?", + "Cancel": "Annulla", "Change": "Cambia", - "Chat_ended": "Chat chiusa!", + "Chat_ended": "Chat terminata!", "Choose_a_new_department": "Seleziona un nuovo dipartimento", "Close_menu": "Chiudi menu", - "Conversation_finished": "conversazione finito", - "End_chat": "Chiusura chat", - "How_friendly_was_the_chat_agent": "Il servizio chat é stato funzionale?", - "How_knowledgeable_was_the_chat_agent": "Quanto é stato semplice il servizio chat?", - "How_responsive_was_the_chat_agent": "Quanto é stato reattivo il servizio chat?", - "How_satisfied_were_you_with_this_chat": "Quanto sei soddisfatto con questa chat?", + "Conversation_finished": "Conversazione terminata", + "End_chat": "Termina chat", + "How_friendly_was_the_chat_agent": "Quanto amichevole era l'operatore?", + "How_knowledgeable_was_the_chat_agent": "Quanto ben informato era l'operatore?", + "How_responsive_was_the_chat_agent": "Quanto efficiente era l'operatore?", + "How_satisfied_were_you_with_this_chat": "Quanto sei soddisfatto di questa chat?", "Installation": "Installazione", "New_messages": "Nuovi messaggi", "No": "No", "Options": "Opzioni", "Please_answer_survey": "Hai un momento per rispondere a un rapido sondaggio su questa chat?", - "Please_choose_a_department": "Prego scegliere un dipartimento", - "Please_fill_name_and_email": "Compila nome e indirizzo e-mail", - "Powered_by": "Powered by", + "Please_choose_a_department": "Si prega di scegliere un dipartimento", + "Please_fill_name_and_email": "Si prega di compilare il nome e l'email", + "Powered_by": "Tecnologia di", "Request_video_chat": "Richiedi video chat", "Select_a_department": "Seleziona un reparto", + "Switch_department": "Cambia dipartimento", + "Department_switched": "Dipartimento cambiato", "Send": "Invia", "Skip": "Salta", "Start_Chat": "Avvia chat", "Survey": "Sondaggio", - "Survey_instructions": "Vota ogni domanda secondo la tua soddisfazione, 1 significa che sei completamente insoddisfatto e 5 significa che sei completamente soddisfatto.", + "Survey_instructions": "Vota ogni domanda secondo il tuo senso di soddisfazione, 1 significa che sei completamente insoddisfatto e 5 significa che sei completamente soddisfatto.", "Thank_you_for_your_feedback": "Grazie per il tuo feedback", "Thanks_We_ll_get_back_to_you_soon": "Grazie! Torneremo al più presto.", - "transcript_sent": "Invio trascrizione", - "Type_your_email": "Inserisci la tua e-mail", + "transcript_sent": "Trascrizione inviata", + "Type_your_email": "Inserisci la tua email", "Type_your_message": "Inserisci il tuo messaggio", - "Type_your_name": "Scrivi il tuo nome", - "User_joined": "é entrato", - "User_left": "Utente ha lasciato", - "We_are_offline_Sorry_for_the_inconvenience": "Non siamo in linea. Ci dispiace per l'inconveniente.", + "Type_your_name": "Inserisci il tuo nome", + "User_joined": "L'utente si è unito", + "User_left": "L'utente ha abbandonato", + "We_are_offline_Sorry_for_the_inconvenience": "Siamo offline. Ci dispiace per l'inconveniente.", "Yes": "Si", "You": "Tu", "You_must_complete_all_fields": "È necessario completare tutti i campi" diff --git a/packages/rocketchat-livechat/.app/i18n/ko.i18n.json b/packages/rocketchat-livechat/.app/i18n/ko.i18n.json index 04b448a9da5..4b8d8bc0aaa 100644 --- a/packages/rocketchat-livechat/.app/i18n/ko.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/ko.i18n.json @@ -1,6 +1,6 @@ { "Additional_Feedback": "추가 의견", - "Appearance": "모양", + "Appearance": "보기", "Are_you_sure_do_you_want_end_this_chat": "이 채팅을 정말 끝내시겠습니까?", "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "현재 진행중인 채팅을 종료하고 부서를 변경하시겠습니까?", "Cancel": "취소", diff --git a/packages/rocketchat-livechat/.app/i18n/ru.i18n.json b/packages/rocketchat-livechat/.app/i18n/ru.i18n.json index 1397a579a87..a9d97d3923e 100644 --- a/packages/rocketchat-livechat/.app/i18n/ru.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/ru.i18n.json @@ -4,7 +4,9 @@ "Are_you_sure_do_you_want_end_this_chat": "Вы уверены что хотите завершить этот чат?", "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Вы действительно хотите завершить этот чат и сменить отдел?", "Cancel": "Отмена", + "Change": "Изменить", "Chat_ended": "Чат закончен!", + "Choose_a_new_department": "Выберите новый отдел", "Close_menu": "Закрыть меню", "Conversation_finished": "Разговор закончен", "End_chat": "Закончить чат", @@ -18,10 +20,12 @@ "Options": "Параметры", "Please_answer_survey": "Пожалуйста, уделите время, чтобы ответить на несколько вопросов об этом чате", "Please_choose_a_department": "Пожалуйста, выберете отдел", - "Please_fill_name_and_email": "Введите имя и электронный адрес", + "Please_fill_name_and_email": "Введите имя и адрес электронной почты", "Powered_by": "Представлен", "Request_video_chat": "Запрос чата с видео", - "Select_a_department": "Выберите группу", + "Select_a_department": "Выберите отдел", + "Switch_department": "Сменить отдел", + "Department_switched": "Отдел сменён", "Send": "Отправить", "Skip": "Пропустить", "Start_Chat": "Начать чат", diff --git a/packages/rocketchat-livechat/.app/i18n/zh.i18n.json b/packages/rocketchat-livechat/.app/i18n/zh.i18n.json index 22c70bbf645..ba7fcdc4a50 100644 --- a/packages/rocketchat-livechat/.app/i18n/zh.i18n.json +++ b/packages/rocketchat-livechat/.app/i18n/zh.i18n.json @@ -2,8 +2,11 @@ "Additional_Feedback": "额外反馈", "Appearance": "外观", "Are_you_sure_do_you_want_end_this_chat": "你确定要结束这个聊天?", + "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "你确定你要结束这个聊天并且切换部门?", "Cancel": "取消", + "Change": "改变", "Chat_ended": "对话已结束!", + "Choose_a_new_department": "选择一个新部门", "Close_menu": "关闭菜单", "Conversation_finished": "对话已结束", "End_chat": "结束对话", @@ -16,6 +19,7 @@ "No": "否", "Options": "选项", "Please_answer_survey": "请花几分钟来反馈这次交谈的体验", + "Please_choose_a_department": "请选择一个新部门", "Please_fill_name_and_email": "请填写姓名和电子邮箱地址", "Powered_by": "提供:", "Request_video_chat": "请求视频聊天", diff --git a/packages/rocketchat-livechat/.app/imports/client/visitor.js b/packages/rocketchat-livechat/.app/imports/client/visitor.js index ccc0937d427..ad121134c95 100644 --- a/packages/rocketchat-livechat/.app/imports/client/visitor.js +++ b/packages/rocketchat-livechat/.app/imports/client/visitor.js @@ -65,7 +65,8 @@ export default { // notification sound if (Session.equals('sound', true) && msg.u._id !== this.getId()) { - $('#chatAudioNotification')[0].play(); + const audio = document.getElementById('chatAudioNotification'); + audio.play(); } } }); diff --git a/packages/rocketchat-livechat/.app/package.json b/packages/rocketchat-livechat/.app/package.json index e0e9add70d3..852c388843c 100644 --- a/packages/rocketchat-livechat/.app/package.json +++ b/packages/rocketchat-livechat/.app/package.json @@ -22,7 +22,7 @@ "dependencies": { "autolinker": "^1.4.3", "jquery": "^3.2.1", - "babel-runtime": "^6.23.0", + "babel-runtime": "^6.25.0", "bcrypt": "^1.0.2", "moment": "^2.18.1", "toastr": "^2.1.2" diff --git a/packages/rocketchat-livechat/app/i18n/af.i18n.json b/packages/rocketchat-livechat/app/i18n/af.i18n.json new file mode 100644 index 00000000000..bb2c6a63ae4 --- /dev/null +++ b/packages/rocketchat-livechat/app/i18n/af.i18n.json @@ -0,0 +1,4 @@ +{ + "Additional_Feedback": "Bykomende terugvoer", + "No": "Nee" +} \ No newline at end of file diff --git a/packages/rocketchat-livechat/app/i18n/mn.i18n.json b/packages/rocketchat-livechat/app/i18n/mn.i18n.json new file mode 100644 index 00000000000..394fd9205b8 --- /dev/null +++ b/packages/rocketchat-livechat/app/i18n/mn.i18n.json @@ -0,0 +1,3 @@ +{ + "Additional_Feedback": "Нэмэлт санал хүсэлт" +} \ No newline at end of file diff --git a/packages/rocketchat-livechat/app/i18n/th-TH.i18n.json b/packages/rocketchat-livechat/app/i18n/th-TH.i18n.json new file mode 100644 index 00000000000..62037b97217 --- /dev/null +++ b/packages/rocketchat-livechat/app/i18n/th-TH.i18n.json @@ -0,0 +1,46 @@ +{ + "Additional_Feedback": "ความคิดเห็นเพิ่มเติม", + "Appearance": "ลักษณะภายนอก", + "Are_you_sure_do_you_want_end_this_chat": "คุณต้องการที่จะจบการสนทนาไช่หรือไม่", + "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "คุณต้องการที่จะจบการสนทนาและเปลี่ยนแผนกไช่หรือไม่", + "Cancel": "ยกเลิก", + "Change": "เปลี่ยน", + "Chat_ended": "การสนทนาจบสิ้นแล้ว!", + "Choose_a_new_department": "เลือกแผนกใหม่", + "Close_menu": "ปิดตัวเลือก", + "Conversation_finished": "การสนทนาเสร็จสิ้นแล้ว", + "End_chat": "จบการสนทนา", + "How_friendly_was_the_chat_agent": "Chat agent เป็นมิตรแค่ไหน?", + "How_knowledgeable_was_the_chat_agent": "Chat agent มีความฉลาดแค่ไหน?", + "How_responsive_was_the_chat_agent": "Chat agent ตอบสนองดีแค่ไหน?", + "How_satisfied_were_you_with_this_chat": "คุณพึงพอใจใน Chat นี้แค่ไหน?", + "Installation": "การติดตั้ง", + "New_messages": "ข้อความใหม่", + "No": "ไม่", + "Options": "ตัวเลือก", + "Please_answer_survey": "กรุณาสละเวลาตอบแบบสอบถามเกี่ยวกับ Chat นี้", + "Please_choose_a_department": "กรุณาเลือกแผนก", + "Please_fill_name_and_email": "กรุณากรอกชื่อและอีเมล์", + "Powered_by": "ถูกสร้างโดย", + "Request_video_chat": "ร้องขอการสนทนาแบบวีดีโอ", + "Select_a_department": "เลือกแผนก", + "Switch_department": "เปลี่ยนแผนก", + "Department_switched": "แผนกถูกเปลี่ยนแล้ว", + "Send": "ส่ง", + "Skip": "ข้าม", + "Start_Chat": "เริ่มการสนทนา", + "Survey": "แบบสอบถาม", + "Survey_instructions": "ให้คะแนนคำถามตามความพอใจ, 1 แปลว่าไม่พอใจอย่างมากและ 5 แปลว่าพอใจอย่างที่สุด", + "Thank_you_for_your_feedback": "ขอบคุณสำหรับความคิดเห็น", + "Thanks_We_ll_get_back_to_you_soon": "ขอบคุณ! เราจะติดต่อกลับโดยเร็ว", + "transcript_sent": "สำเนาถูกส่งแล้ว", + "Type_your_email": "พิมอีเมล์ของคุณ", + "Type_your_message": "พิมข้อความของคุณ", + "Type_your_name": "พิมชื่อของคุณ", + "User_joined": "ผู้ใช้งานเข้าร่วมแล้ว", + "User_left": "ผู้ใช้งานออกแล้ว", + "We_are_offline_Sorry_for_the_inconvenience": "เรากำลังออฟไลน์ ขออภัยในความไม่สะดวก", + "Yes": "ไช่", + "You": "คุณ", + "You_must_complete_all_fields": "คุณต้องกรอกข้อมูลทุกช่อง" +} \ No newline at end of file diff --git a/packages/rocketchat-livechat/app/i18n/vi-VN.i18n.json b/packages/rocketchat-livechat/app/i18n/vi-VN.i18n.json new file mode 100644 index 00000000000..c76b1311752 --- /dev/null +++ b/packages/rocketchat-livechat/app/i18n/vi-VN.i18n.json @@ -0,0 +1,3 @@ +{ + "Additional_Feedback": "Phản hồi bổ sung" +} \ No newline at end of file diff --git a/packages/rocketchat-livechat/client/stylesheets/livechat.less b/packages/rocketchat-livechat/client/stylesheets/livechat.less index 3d928e9b278..9b5daf989d4 100644 --- a/packages/rocketchat-livechat/client/stylesheets/livechat.less +++ b/packages/rocketchat-livechat/client/stylesheets/livechat.less @@ -621,18 +621,14 @@ } .livechat-section { - opacity: 0.5; - transition: opacity 0.4s ease; - - &.available { - opacity: 1; - } + margin-bottom: 32px; } .livechat-status { float: right; margin-right: 10px; font-size: 20px; + color: #9d9fa3; } .external-message { diff --git a/packages/rocketchat-livechat/client/ui.js b/packages/rocketchat-livechat/client/ui.js index 9842f10c2af..a2f95eb9c70 100644 --- a/packages/rocketchat-livechat/client/ui.js +++ b/packages/rocketchat-livechat/client/ui.js @@ -1,6 +1,6 @@ AccountBox.addItem({ name: 'Livechat', - icon: 'icon-chat-empty', + icon: 'livechat', href: 'livechat-current-chats', sideNav: 'livechatFlex', condition: () => { @@ -12,25 +12,16 @@ RocketChat.TabBar.addButton({ groups: ['live'], id: 'visitor-info', i18nTitle: 'Visitor_Info', - icon: 'icon-info-circled', + icon: 'info-circled', template: 'visitorInfo', order: 0 }); -// RocketChat.TabBar.addButton({ -// groups: ['livechat'], -// id: 'visitor-navigation', -// i18nTitle: 'Visitor_Navigation', -// icon: 'icon-history', -// template: 'visitorNavigation', -// order: 10 -// }); - RocketChat.TabBar.addButton({ groups: ['live'], id: 'visitor-history', i18nTitle: 'Past_Chats', - icon: 'icon-chat', + icon: 'chat', template: 'visitorHistory', order: 11 }); @@ -45,7 +36,7 @@ RocketChat.TabBar.addButton({ groups: ['live'], id: 'external-search', i18nTitle: 'Knowledge_Base', - icon: 'icon-lightbulb', + icon: 'lightbulb', template: 'externalSearch', order: 10 }); diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html index 21e6041d869..de4a6b4d398 100644 --- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html +++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html @@ -1,77 +1,75 @@ -
{{username}}
-{{name}}
+ {{#if editing}} + {{> visitorEdit (editDetails)}} + {{/if}} + {{#if forwarding}} + {{> visitorForward (forwardDetails)}} + {{/if}} +{{username}}
+{{name}}
--
- {{#if utc}}
- {{userTime}} (UTC {{utc}}) {{/if}} - {{#each visitorEmails}}
- {{address}}{{#if verified}} {{/if}} {{/each}} - {{#each phone}}
- {{phoneNumber}} {{/each}} - {{#if lastLogin}}
- {{_ "Created_at"}}: {{createdAt}} {{/if}} - {{#if lastLogin}}
- {{_ "Last_login"}}: {{lastLogin}} {{/if}} - {{#if ip}}
- {{ip}} {{/if}} - {{#if os}}
- {{os}} {{/if}} - {{#if browser}}
- {{browser}} {{/if}} -
-
+ {{#if utc}}
- {{userTime}} (UTC {{utc}}) {{/if}} + {{#each visitorEmails}}
- {{address}}{{#if verified}} {{/if}} {{/each}} + {{#each phone}}
- {{phoneNumber}} {{/each}} + {{#if lastLogin}}
- {{_ "Created_at"}}: {{createdAt}} {{/if}} + {{#if lastLogin}}
- {{_ "Last_login"}}: {{lastLogin}} {{/if}} + {{#if ip}}
- {{ip}} {{/if}} + {{#if os}}
- {{os}} {{/if}} + {{#if browser}}
- {{browser}} {{/if}} +
-
- {{#if sms}}
-
- {{_ "SMS_Enabled"}} - {{/if}} - {{#if topic}} -
- {{_ "Topic"}}: {{topic}} - {{/if}} - {{#if tags}} -
- {{_ "Tags"}}: {{joinTags}} - {{/if}} -
-
+ {{#if sms}}
+
- {{_ "SMS_Enabled"}} + {{/if}} + {{#if topic}} +
- {{_ "Topic"}}: {{topic}} + {{/if}} + {{#if tags}} +
- {{_ "Tags"}}: {{joinTags}} + {{/if}} +
{{_ "Custom_Fields"}}
+ {{#if customFields}} +{{_ "Custom_Fields"}}
--
- {{#each customFields}}
-
- {{label}}: {{value}} - {{/each}} -
-
+ {{#each customFields}}
+
- {{label}}: {{value}} + {{/each}} +
+
+
{{#with available}}
{{/with}}
@@ -9,36 +9,31 @@
{{#if guestPool}}
{{#if isLivechatAvailable}}
-
+
{{_ "Incoming_Livechats"}}
-
- {{#each inquiries}}
- {{> chatRoomItem }}
+
+ {{#each room in inquiries}}
+ {{> chatRoomItem room }}
{{else}}
- - {{_ "No_livechats" }}
+ {{_ "No_livechats" }}
{{/each}}
{{/if}}
-
+
{{_ "Open_Livechats"}}
{{/if}}
-
+
{{#if showQueueLink}}
- -
-
-
- {{_ "Queue"}}
-
-
+ {{> sidebarItem active=activeLivechatQueue pathSection="livechat-queue" icon="queue" name="Queue"}}
{{/if}}
- {{#each rooms}}
- {{> chatRoomItem }}
+ {{#each room in rooms}}
+ {{> chatRoomItem room }}
{{else}}
- - {{_ "No_livechats" }}
+ {{_ "No_livechats" }}
{{/each}}
diff --git a/packages/rocketchat-livechat/client/views/sideNav/livechat.js b/packages/rocketchat-livechat/client/views/sideNav/livechat.js
index 087760f6867..26b7af6b240 100644
--- a/packages/rocketchat-livechat/client/views/sideNav/livechat.js
+++ b/packages/rocketchat-livechat/client/views/sideNav/livechat.js
@@ -62,16 +62,12 @@ Template.livechat.helpers({
const statusLivechat = Template.instance().statusLivechat.get();
return {
- status: statusLivechat === 'available' ? 'status-online' : 'status-offline',
+ status: statusLivechat === 'available' ? 'status-online' : '',
icon: statusLivechat === 'available' ? 'icon-toggle-on' : 'icon-toggle-off',
hint: statusLivechat === 'available' ? t('Available') : t('Not_Available')
};
},
- livechatAvailable() {
- return Template.instance().statusLivechat.get();
- },
-
isLivechatAvailable() {
return Template.instance().statusLivechat.get() === 'available';
},
diff --git a/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html b/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html
index 4b348a75752..b1e5a1f90a3 100644
--- a/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html
+++ b/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html
@@ -1,23 +1,24 @@
-
-
- {{_ "Livechat"}}
-
-
-
-
-
+
diff --git a/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.js b/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.js
index 73366072722..e9b55bc890e 100644
--- a/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.js
+++ b/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.js
@@ -1,22 +1,16 @@
Template.livechatFlex.helpers({
- active(...routes) {
- FlowRouter.watchPathChange();
- if (routes.indexOf(FlowRouter.current().route.name) !== -1) {
- return 'active';
- }
+ menuItem(name, icon, section) {
+ return {
+ name: t(name),
+ icon,
+ pathSection: section,
+ darken: true
+ };
}
});
Template.livechatFlex.events({
- 'mouseenter header'() {
- SideNav.overArrow();
- },
-
- 'mouseleave header'() {
- SideNav.leaveArrow();
- },
-
- 'click header'() {
+ 'click [data-action="back"]'() {
SideNav.closeFlex();
}
});
diff --git a/packages/rocketchat-livechat/roomType.js b/packages/rocketchat-livechat/roomType.js
index de542583e11..84e0ee61611 100644
--- a/packages/rocketchat-livechat/roomType.js
+++ b/packages/rocketchat-livechat/roomType.js
@@ -1,7 +1,7 @@
/* globals openRoom, LivechatInquiry */
RocketChat.roomTypes.add('l', 5, {
- icon: 'icon-chat-empty',
+ icon: 'livechat',
label: 'Livechat',
route: {
name: 'live',
diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js
index 77890675886..d3e19ce5478 100644
--- a/packages/rocketchat-livechat/server/lib/Livechat.js
+++ b/packages/rocketchat-livechat/server/lib/Livechat.js
@@ -125,7 +125,7 @@ RocketChat.Livechat = {
if (this.connection) {
userData.userAgent = this.connection.httpHeaders['user-agent'];
- userData.ip = this.connection.httpHeaders['x-real-ip'] || this.connection.clientAddress;
+ userData.ip = this.connection.httpHeaders['x-real-ip'] || this.connection.httpHeaders['x-forwarded-for'] || this.connection.clientAddress;
userData.host = this.connection.httpHeaders.host;
}
@@ -316,6 +316,8 @@ RocketChat.Livechat = {
alert: true,
open: true,
unread: 1,
+ userMentions: 1,
+ groupMentions: 0,
code: room.code,
u: {
_id: agent.agentId,
diff --git a/packages/rocketchat-livechat/server/lib/QueueMethods.js b/packages/rocketchat-livechat/server/lib/QueueMethods.js
index c1e8d887a6a..425dc26fdde 100644
--- a/packages/rocketchat-livechat/server/lib/QueueMethods.js
+++ b/packages/rocketchat-livechat/server/lib/QueueMethods.js
@@ -40,6 +40,8 @@ RocketChat.QueueMethods = {
alert: true,
open: true,
unread: 1,
+ userMentions: 1,
+ groupMentions: 0,
code: roomCode,
u: {
_id: agent.agentId,
diff --git a/packages/rocketchat-livechat/server/methods/takeInquiry.js b/packages/rocketchat-livechat/server/methods/takeInquiry.js
index 5d73a1fadda..f1277d8d4cc 100644
--- a/packages/rocketchat-livechat/server/methods/takeInquiry.js
+++ b/packages/rocketchat-livechat/server/methods/takeInquiry.js
@@ -24,6 +24,8 @@ Meteor.methods({
alert: true,
open: true,
unread: 1,
+ userMentions: 1,
+ groupMentions: 0,
code: inquiry.code,
u: {
_id: agent.agentId,
diff --git a/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html b/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html
index e00707e7b5f..637e0a59621 100644
--- a/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html
+++ b/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html
@@ -1,5 +1,5 @@
-
+
diff --git a/packages/rocketchat-mapview/client/mapview.js b/packages/rocketchat-mapview/client/mapview.js
index fefce23a838..1d2285b54c2 100644
--- a/packages/rocketchat-mapview/client/mapview.js
+++ b/packages/rocketchat-mapview/client/mapview.js
@@ -5,15 +5,15 @@
function MapView(message) {
- // get MapView settings
+ // get MapView settings
const mv_googlekey = RocketChat.settings.get('MapView_GMapsAPIKey');
if (message.location) {
- // GeoJSON is reversed - ie. [lng, lat]
+ // GeoJSON is reversed - ie. [lng, lat]
const [longitude, latitude] = message.location.coordinates;
- // confirm we have an api key set, and generate the html required for the mapview
+ // confirm we have an api key set, and generate the html required for the mapview
if (mv_googlekey && mv_googlekey.length) {
message.html = `
`;
} else {
diff --git a/packages/rocketchat-markdown/markdown.js b/packages/rocketchat-markdown/markdown.js
index 5f0269f99fa..2bcb60d1cd2 100644
--- a/packages/rocketchat-markdown/markdown.js
+++ b/packages/rocketchat-markdown/markdown.js
@@ -8,7 +8,11 @@ class MarkdownClass {
return this.parseNotEscaped(_.escapeHTML(text));
}
- parseNotEscaped(msg) {
+ parseNotEscaped(msg, message) {
+ if (message && message.tokens == null) {
+ message.tokens = [];
+ }
+
const schemes = RocketChat.settings.get('Markdown_SupportSchemesForLink').split(',').join('|');
if (RocketChat.settings.get('Markdown_Headers')) {
@@ -53,19 +57,32 @@ class MarkdownClass {
// Support 
msg = msg.replace(new RegExp(`!\\[([^\\]]+)\\]\\(((?:${ schemes }):\\/\\/[^\\)]+)\\)`, 'gm'), function(match, title, url) {
const target = url.indexOf(Meteor.absoluteUrl()) === 0 ? '' : '_blank';
- return ``;
+ const html = ``;
+
+ if (message && message.tokens) {
+ const token = `=!=${ Random.id() }=!=`;
+
+ message.tokens.push({
+ token,
+ text: html
+ });
+
+ return token;
+ }
+
+ return html;
});
// Support [Text](http://link)
msg = msg.replace(new RegExp(`\\[([^\\]]+)\\]\\(((?:${ schemes }):\\/\\/[^\\)]+)\\)`, 'gm'), function(match, title, url) {
const target = url.indexOf(Meteor.absoluteUrl()) === 0 ? '' : '_blank';
- return `${ _.escapeHTML(title) }`;
+ return `${ _.escapeHTML(title) }`;
});
// Support
msg = msg.replace(new RegExp(`(?:<|<)((?:${ schemes }):\\/\\/[^\\|]+)\\|(.+?)(?=>|>)(?:>|>)`, 'gm'), (match, url, title) => {
const target = url.indexOf(Meteor.absoluteUrl()) === 0 ? '' : '_blank';
- return `${ _.escapeHTML(title) }`;
+ return `${ _.escapeHTML(title) }`;
});
if (typeof window !== 'undefined' && window !== null ? window.rocketDebug : undefined) { console.log('Markdown', msg); }
@@ -80,7 +97,7 @@ RocketChat.Markdown = Markdown;
// renderMessage already did html escape
const MarkdownMessage = (message) => {
if (_.trim(message != null ? message.html : undefined)) {
- message.html = Markdown.parseNotEscaped(message.html);
+ message.html = Markdown.parseNotEscaped(message.html, message);
}
return message;
diff --git a/packages/rocketchat-markdown/markdowncode.js b/packages/rocketchat-markdown/markdowncode.js
index 65f00ce79ff..e00b030d01b 100644
--- a/packages/rocketchat-markdown/markdowncode.js
+++ b/packages/rocketchat-markdown/markdowncode.js
@@ -60,29 +60,16 @@ class MarkdownCode {
if (codeMatch != null) {
// Process highlight if this part is code
- let code;
- let lang;
- let result;
const singleLine = codeMatch[0].indexOf('\n') === -1;
-
- if (singleLine) {
- lang = '';
- code = _.unescapeHTML(codeMatch[1] + codeMatch[2]);
- } else {
- lang = codeMatch[1];
- code = _.unescapeHTML(codeMatch[2]);
- }
-
- if (s.trim(lang) === '') {
- lang = '';
- }
-
- if (!Array.from(hljs.listLanguages()).includes(s.trim(lang))) {
- result = hljs.highlightAuto((lang + code));
- } else {
- result = hljs.highlight(s.trim(lang), code);
- }
-
+ const lang = !singleLine && Array.from(hljs.listLanguages()).includes(s.trim(codeMatch[1])) ? s.trim(codeMatch[1]) : '';
+ const code =
+ singleLine ?
+ _.unescapeHTML(codeMatch[1]) :
+ lang === '' ?
+ _.unescapeHTML(codeMatch[1] + codeMatch[2]) :
+ _.unescapeHTML(codeMatch[2]);
+
+ const result = lang === '' ? hljs.highlightAuto((lang + code)) : hljs.highlight(lang, code);
const token = `=!=${ Random.id() }=!=`;
message.tokens.push({
diff --git a/packages/rocketchat-markdown/package.js b/packages/rocketchat-markdown/package.js
index 4c24cce6976..d4dcf611e88 100644
--- a/packages/rocketchat-markdown/package.js
+++ b/packages/rocketchat-markdown/package.js
@@ -18,13 +18,3 @@ Package.onUse(function(api) {
api.addFiles('markdown.js');
api.addFiles('markdowncode.js');
});
-
-Package.onTest(function(api) {
- api.use([
- 'sanjo:jasmine@0.20.2',
- 'rocketchat:lib',
- 'rocketchat:markdown'
- ]);
-
- api.addFiles('tests/jasmine/client/unit/markdown.spec.js', 'client');
-});
diff --git a/packages/rocketchat-mentions-flextab/client/actionButton.js b/packages/rocketchat-mentions-flextab/client/actionButton.js
index 9f233569363..9061f871174 100644
--- a/packages/rocketchat-mentions-flextab/client/actionButton.js
+++ b/packages/rocketchat-mentions-flextab/client/actionButton.js
@@ -7,6 +7,9 @@ Meteor.startup(function() {
action() {
const message = this._arguments[1];
RocketChat.MessageAction.hideDropDown();
+ if (window.matchMedia('(max-width: 500px)').matches) {
+ Template.instance().tabBar.close();
+ }
return RoomHistoryManager.getSurroundingMessages(message, 50);
},
validation(message) {
diff --git a/packages/rocketchat-mentions-flextab/client/tabBar.js b/packages/rocketchat-mentions-flextab/client/tabBar.js
index 272b29ede31..c59eab76cb0 100644
--- a/packages/rocketchat-mentions-flextab/client/tabBar.js
+++ b/packages/rocketchat-mentions-flextab/client/tabBar.js
@@ -3,7 +3,7 @@ Meteor.startup(function() {
groups: ['channel', 'group'],
id: 'mentions',
i18nTitle: 'Mentions',
- icon: 'icon-at',
+ icon: 'at',
template: 'mentionsFlexTab',
order: 3
});
diff --git a/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html b/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html
index 42c5a38ef74..2c6e27ff6b0 100644
--- a/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html
+++ b/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html
@@ -1,24 +1,22 @@
-
-
{{#with available}}
{{/with}}
@@ -9,36 +9,31 @@
{{#if guestPool}}
{{#if isLivechatAvailable}}
-
+
{{_ "Incoming_Livechats"}}
-
- {{#each inquiries}}
- {{> chatRoomItem }}
+
+ {{#each room in inquiries}}
+ {{> chatRoomItem room }}
{{else}}
- - {{_ "No_livechats" }}
+ {{_ "No_livechats" }}
{{/each}}
{{/if}}
-
+
{{_ "Open_Livechats"}}
{{/if}}
-
+
{{#if showQueueLink}}
- -
-
-
- {{_ "Queue"}}
-
-
+ {{> sidebarItem active=activeLivechatQueue pathSection="livechat-queue" icon="queue" name="Queue"}}
{{/if}}
- {{#each rooms}}
- {{> chatRoomItem }}
+ {{#each room in rooms}}
+ {{> chatRoomItem room }}
{{else}}
- - {{_ "No_livechats" }}
+ {{_ "No_livechats" }}
{{/each}}
{{_ "Incoming_Livechats"}}
--
- {{#each inquiries}}
- {{> chatRoomItem }}
+
- {{_ "No_livechats" }} +
- - - - {{_ "Queue"}} - - + {{> sidebarItem active=activeLivechatQueue pathSection="livechat-queue" icon="queue" name="Queue"}} {{/if}} - {{#each rooms}} - {{> chatRoomItem }} + {{#each room in rooms}} + {{> chatRoomItem room }} {{else}} -
- {{_ "No_livechats" }} +
-
+ {{#each room in inquiries}}
+ {{> chatRoomItem room }}
{{else}}
-
{{_ "No_livechats" }}
{{/each}}
+
{{_ "Open_Livechats"}}
{{/if}}
-
+
{{#if showQueueLink}}
- {{_ "No_livechats" }}
{{/each}}
-
{{#if showQueueLink}}
-
{{_ "No_livechats" }}
{{/each}}