diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index c4685444b7ad4..547eb234f11a7 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/ubi8/nodejs-12 -ENV RC_VERSION 3.10.0 +ENV RC_VERSION 3.10.1 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 9c311669cbc21..79d71989f9a7c 100644 --- a/.github/history.json +++ b/.github/history.json @@ -53685,6 +53685,202 @@ "4.0" ], "pull_requests": [] + }, + "3.8.5": { + "node_version": "12.18.4", + "npm_version": "6.14.8", + "apps_engine_version": "1.19.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "19978", + "title": "Regression: Fix oembed", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego" + ] + } + ] + }, + "3.9.4": { + "node_version": "12.18.4", + "npm_version": "6.14.8", + "apps_engine_version": "1.21.0-alpha.4235", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "19978", + "title": "Regression: Fix oembed", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "19830", + "title": "[FIX] Omnichannel Departments Canned Responses", + "userLogin": "gabriellsh", + "milestone": "3.9.4", + "contributors": [ + "gabriellsh", + "web-flow", + "renatobecker", + "dougfabris" + ] + }, + { + "pr": "19945", + "title": "[FIX] Room scrolling to top after returns to a opened room", + "userLogin": "ggazzo", + "milestone": "3.9.4", + "contributors": [ + "ggazzo", + "tassoevan", + "web-flow" + ] + }, + { + "pr": "19935", + "title": "[FIX] Status on searchlist", + "userLogin": "gabriellsh", + "milestone": "3.9.4", + "contributors": [ + "gabriellsh", + "tassoevan", + "web-flow" + ] + } + ] + }, + "3.10.1": { + "node_version": "12.18.4", + "npm_version": "6.14.8", + "apps_engine_version": "1.21.0-alpha.4235", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "20073", + "title": "[FIX] Actions from User Info panel", + "userLogin": "Darshilp326", + "description": "Users can be removed from channels without any error message.", + "milestone": "3.10.1", + "contributors": [ + "Darshilp326" + ] + }, + { + "pr": "20114", + "title": "[FIX] Messages being updated when not required after user changes his profile", + "userLogin": "sampaiodiego", + "milestone": "3.10.1", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "19953", + "title": "[FIX][ENTERPRISE] Omnichannel custom fields not storing additional form values ", + "userLogin": "rafaelblink", + "milestone": "3.10.1", + "contributors": [ + "rafaelblink", + "renatobecker", + "web-flow" + ] + }, + { + "pr": "20089", + "title": "[FIX] Omnichannel rooms breaking after return to queue or forward", + "userLogin": "gabriellsh", + "milestone": "3.10.1", + "contributors": [ + "gabriellsh", + "renatobecker", + "web-flow" + ] + }, + { + "pr": "20093", + "title": "[FIX] Omnichannel raw model importing meteor dependency", + "userLogin": "renatobecker", + "milestone": "3.10.1", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "20061", + "title": "[FIX] User Audio notification preference not being applied", + "userLogin": "sampaiodiego", + "milestone": "3.10.1", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "20003", + "title": "[FIX] OAuth users being asked to change password on second login", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.10.1", + "contributors": [ + "pierre-lehnen-rc", + "sampaiodiego" + ] + }, + { + "pr": "20022", + "title": "[FIX] Omnichannel Agents unable to take new chats in the queue", + "userLogin": "rafaelblink", + "milestone": "3.10.1", + "contributors": [ + "rafaelblink", + "renatobecker" + ] + }, + { + "pr": "20007", + "title": "[FIX] Omnichannel Business Hours form is not being rendered", + "userLogin": "rafaelblink", + "milestone": "3.10.1", + "contributors": [ + "rafaelblink", + "renatobecker", + "web-flow" + ] + }, + { + "pr": "19965", + "title": "[FIX] Agent information panel not rendering", + "userLogin": "rafaelblink", + "milestone": "3.10.1", + "contributors": [ + "rafaelblink", + "renatobecker", + "web-flow" + ] + }, + { + "pr": "19997", + "title": "[FIX] Creation of Omnichannel rooms not working correctly through the Apps when the agent parameter is set", + "userLogin": "murtaza98", + "milestone": "3.10.1", + "contributors": [ + "murtaza98" + ] + } + ] } } } \ No newline at end of file diff --git a/.snapcraft/resources/prepareRocketChat b/.snapcraft/resources/prepareRocketChat index e03dd7765b604..5f548f1159eba 100755 --- a/.snapcraft/resources/prepareRocketChat +++ b/.snapcraft/resources/prepareRocketChat @@ -1,6 +1,6 @@ #!/bin/bash -curl -SLf "https://releases.rocket.chat/3.10.0/download/" -o rocket.chat.tgz +curl -SLf "https://releases.rocket.chat/3.10.1/download/" -o rocket.chat.tgz tar xf rocket.chat.tgz --strip 1 diff --git a/.snapcraft/snap/snapcraft.yaml b/.snapcraft/snap/snapcraft.yaml index 79ac3108e1411..6bcd1f19d9517 100644 --- a/.snapcraft/snap/snapcraft.yaml +++ b/.snapcraft/snap/snapcraft.yaml @@ -7,7 +7,7 @@ # 5. `snapcraft snap` name: rocketchat-server -version: 3.10.0 +version: 3.10.1 summary: Rocket.Chat server description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/ confinement: strict diff --git a/HISTORY.md b/HISTORY.md index 9e9625e1128cb..e67cba033d460 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,53 @@ +# 3.10.1 +`2021-01-08 · 11 🐛 · 7 👩‍💻👨‍💻` + +### Engine versions +- Node: `12.18.4` +- NPM: `6.14.8` +- MongoDB: `3.4, 3.6, 4.0` +- Apps-Engine: `1.21.0-alpha.4235` + +### 🐛 Bug fixes + + +- **ENTERPRISE:** Omnichannel custom fields not storing additional form values ([#19953](https://github.com/RocketChat/Rocket.Chat/pull/19953)) + +- Actions from User Info panel ([#20073](https://github.com/RocketChat/Rocket.Chat/pull/20073) by [@Darshilp326](https://github.com/Darshilp326)) + + Users can be removed from channels without any error message. + +- Agent information panel not rendering ([#19965](https://github.com/RocketChat/Rocket.Chat/pull/19965)) + +- Creation of Omnichannel rooms not working correctly through the Apps when the agent parameter is set ([#19997](https://github.com/RocketChat/Rocket.Chat/pull/19997)) + +- Messages being updated when not required after user changes his profile ([#20114](https://github.com/RocketChat/Rocket.Chat/pull/20114)) + +- OAuth users being asked to change password on second login ([#20003](https://github.com/RocketChat/Rocket.Chat/pull/20003)) + +- Omnichannel Agents unable to take new chats in the queue ([#20022](https://github.com/RocketChat/Rocket.Chat/pull/20022)) + +- Omnichannel Business Hours form is not being rendered ([#20007](https://github.com/RocketChat/Rocket.Chat/pull/20007)) + +- Omnichannel raw model importing meteor dependency ([#20093](https://github.com/RocketChat/Rocket.Chat/pull/20093)) + +- Omnichannel rooms breaking after return to queue or forward ([#20089](https://github.com/RocketChat/Rocket.Chat/pull/20089)) + +- User Audio notification preference not being applied ([#20061](https://github.com/RocketChat/Rocket.Chat/pull/20061)) + +### 👩‍💻👨‍💻 Contributors 😍 + +- [@Darshilp326](https://github.com/Darshilp326) + +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@gabriellsh](https://github.com/gabriellsh) +- [@murtaza98](https://github.com/murtaza98) +- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) +- [@rafaelblink](https://github.com/rafaelblink) +- [@renatobecker](https://github.com/renatobecker) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.10.0 `2020-12-29 · 6 🎉 · 10 🚀 · 29 🐛 · 39 🔍 · 20 👩‍💻👨‍💻` @@ -243,6 +292,41 @@ - [@thassiov](https://github.com/thassiov) - [@tiagoevanp](https://github.com/tiagoevanp) +# 3.9.4 +`2020-12-31 · 3 🐛 · 1 🔍 · 6 👩‍💻👨‍💻` + +### Engine versions +- Node: `12.18.4` +- NPM: `6.14.8` +- MongoDB: `3.4, 3.6, 4.0` +- Apps-Engine: `1.21.0-alpha.4235` + +### 🐛 Bug fixes + + +- Omnichannel Departments Canned Responses ([#19830](https://github.com/RocketChat/Rocket.Chat/pull/19830)) + +- Room scrolling to top after returns to a opened room ([#19945](https://github.com/RocketChat/Rocket.Chat/pull/19945)) + +- Status on searchlist ([#19935](https://github.com/RocketChat/Rocket.Chat/pull/19935)) + +
+🔍 Minor changes + + +- Regression: Fix oembed ([#19978](https://github.com/RocketChat/Rocket.Chat/pull/19978)) + +
+ +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@dougfabris](https://github.com/dougfabris) +- [@gabriellsh](https://github.com/gabriellsh) +- [@ggazzo](https://github.com/ggazzo) +- [@renatobecker](https://github.com/renatobecker) +- [@sampaiodiego](https://github.com/sampaiodiego) +- [@tassoevan](https://github.com/tassoevan) + # 3.9.3 `2020-12-18 · 2 🐛 · 1 👩‍💻👨‍💻` @@ -538,6 +622,27 @@ - [@sampaiodiego](https://github.com/sampaiodiego) - [@tiagoevanp](https://github.com/tiagoevanp) +# 3.8.5 +`2020-12-31 · 1 🔍 · 1 👩‍💻👨‍💻` + +### Engine versions +- Node: `12.18.4` +- NPM: `6.14.8` +- MongoDB: `3.4, 3.6, 4.0` +- Apps-Engine: `1.19.0` + +
+🔍 Minor changes + + +- Regression: Fix oembed ([#19978](https://github.com/RocketChat/Rocket.Chat/pull/19978)) + +
+ +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.8.4 `2020-12-18 · 2 🐛 · 1 👩‍💻👨‍💻` diff --git a/app/apps/server/bridges/livechat.js b/app/apps/server/bridges/livechat.js index d4adfa35b8384..b48ba38d75191 100644 --- a/app/apps/server/bridges/livechat.js +++ b/app/apps/server/bridges/livechat.js @@ -60,7 +60,7 @@ export class AppLivechatBridge { let agentRoom; if (agent && agent.id) { const user = Users.getAgentInfo(agent.id); - agentRoom = Object.assign({}, { agentId: user._id }); + agentRoom = Object.assign({}, { agentId: user._id, username: user.username }); } const result = await getRoom({ diff --git a/app/authorization/server/startup.js b/app/authorization/server/startup.js index 7db90f9e32c47..a2015e46816f6 100644 --- a/app/authorization/server/startup.js +++ b/app/authorization/server/startup.js @@ -98,7 +98,7 @@ Meteor.startup(function() { { _id: 'save-others-livechat-room-info', roles: ['livechat-manager'] }, { _id: 'remove-closed-livechat-rooms', roles: ['livechat-manager', 'admin'] }, { _id: 'view-livechat-analytics', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-queue', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-queue', roles: ['livechat-agent', 'livechat-manager', 'admin'] }, { _id: 'transfer-livechat-guest', roles: ['livechat-manager', 'admin'] }, { _id: 'manage-livechat-managers', roles: ['livechat-manager', 'admin'] }, { _id: 'manage-livechat-agents', roles: ['livechat-manager', 'admin'] }, diff --git a/app/lib/server/functions/saveUserIdentity.js b/app/lib/server/functions/saveUserIdentity.js index 4294a5b88db0f..a8e0eca2e7d7f 100644 --- a/app/lib/server/functions/saveUserIdentity.js +++ b/app/lib/server/functions/saveUserIdentity.js @@ -38,28 +38,29 @@ export function saveUserIdentity(userId, { _id, name: rawName, username: rawUser } // if coming from old username, update all references - if ((previousUsername && usernameChanged) || (previousName && previousUsername)) { - if (typeof rawUsername !== 'undefined') { - Messages.updateAllUsernamesByUserId(user._id, username); - Messages.updateUsernameOfEditByUserId(user._id, username); - Messages.findByMention(previousUsername).forEach(function(msg) { - const updatedMsg = msg.msg.replace(new RegExp(`@${ previousUsername }`, 'ig'), `@${ username }`); - return Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername(msg._id, previousUsername, username, updatedMsg); - }); - Rooms.replaceUsername(previousUsername, username); - Rooms.replaceMutedUsername(previousUsername, username); - Rooms.replaceUsernameOfUserByUserId(user._id, username); - Subscriptions.setUserUsernameByUserId(user._id, username); + if (previousUsername && usernameChanged && typeof rawUsername !== 'undefined') { + Messages.updateAllUsernamesByUserId(user._id, username); + Messages.updateUsernameOfEditByUserId(user._id, username); + Messages.findByMention(previousUsername).forEach(function(msg) { + const updatedMsg = msg.msg.replace(new RegExp(`@${ previousUsername }`, 'ig'), `@${ username }`); + return Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername(msg._id, previousUsername, username, updatedMsg); + }); + Rooms.replaceUsername(previousUsername, username); + Rooms.replaceMutedUsername(previousUsername, username); + Rooms.replaceUsernameOfUserByUserId(user._id, username); + Subscriptions.setUserUsernameByUserId(user._id, username); - LivechatDepartmentAgents.replaceUsernameOfAgentByUserId(user._id, username); + LivechatDepartmentAgents.replaceUsernameOfAgentByUserId(user._id, username); - const fileStore = FileUpload.getStore('Avatars'); - const file = fileStore.model.findOneByName(previousUsername); - if (file) { - fileStore.model.updateFileNameById(file._id, username); - } + const fileStore = FileUpload.getStore('Avatars'); + const file = fileStore.model.findOneByName(previousUsername); + if (file) { + fileStore.model.updateFileNameById(file._id, username); } + } + // update other references if either the name or username has changed + if (usernameChanged || nameChanged) { // update name and fname of 1-on-1 direct messages Subscriptions.updateDirectNameAndFnameByName(previousUsername, rawUsername && username, rawName && name); diff --git a/app/livechat/client/lib/stream/queueManager.js b/app/livechat/client/lib/stream/queueManager.js index 00db09a0effe3..9d9223db22e33 100644 --- a/app/livechat/client/lib/stream/queueManager.js +++ b/app/livechat/client/lib/stream/queueManager.js @@ -58,7 +58,7 @@ const addGlobalListener = () => { }; -const subscribe = async (userId, isManager) => { +const subscribe = async (userId) => { const config = await call('livechat:getRoutingConfig'); if (config && config.autoAssignAgent) { return; @@ -66,7 +66,7 @@ const subscribe = async (userId, isManager) => { const agentDepartments = (await getAgentsDepartments(userId)).map((department) => department.departmentId); - const cleanUp = agentDepartments.length ? await addListenerForeachDepartment(agentDepartments) : isManager && addGlobalListener(); + const cleanUp = agentDepartments.length ? await addListenerForeachDepartment(agentDepartments) : addGlobalListener(); updateInquiries(await getInquiriesFromAPI()); diff --git a/app/models/server/raw/LivechatDepartmentAgents.js b/app/models/server/raw/LivechatDepartmentAgents.js index 3bcd4032bad80..b5118e78eca08 100644 --- a/app/models/server/raw/LivechatDepartmentAgents.js +++ b/app/models/server/raw/LivechatDepartmentAgents.js @@ -31,4 +31,7 @@ export class LivechatDepartmentAgentsRaw extends BaseRaw { findByDepartmentIds(departmentIds, options = {}) { return this.find({ departmentId: { $in: departmentIds } }, options); } + + // eslint-disable-next-line no-unused-vars + findAgentsByAgentIdAndBusinessHourId(agentId, businessHourId) { return []; } } diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 755476438b82a..58ea23dd30505 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.10.0" + "version": "3.10.1" } diff --git a/client/components/RoomForeword.js b/client/components/RoomForeword.js index 4e20ecce07e0f..aa0cd9c335cce 100644 --- a/client/components/RoomForeword.js +++ b/client/components/RoomForeword.js @@ -13,7 +13,7 @@ const RoomForeword = ({ _id: rid }) => { const user = useUser(); const room = useReactiveValue(useCallback(() => Rooms.findOne({ _id: rid }), [rid])); - if (room.t !== 'd') { + if (room?.t !== 'd') { return t('Start_of_conversation'); } diff --git a/client/providers/OmniChannelProvider.tsx b/client/providers/OmniChannelProvider.tsx index fdaaf672c5824..df7e1735f3958 100644 --- a/client/providers/OmniChannelProvider.tsx +++ b/client/providers/OmniChannelProvider.tsx @@ -7,7 +7,7 @@ import { Notifications } from '../../app/notifications/client'; import { OmnichannelContext, OmnichannelContextValue } from '../contexts/OmnichannelContext'; import { useReactiveValue } from '../hooks/useReactiveValue'; import { useUser, useUserId } from '../contexts/UserContext'; -import { usePermission, useRole } from '../contexts/AuthorizationContext'; +import { usePermission } from '../contexts/AuthorizationContext'; import { useSetting } from '../contexts/SettingsContext'; import { LivechatInquiry } from '../../app/livechat/client/collections/LivechatInquiry'; import { initializeLivechatInquiryStream } from '../../app/livechat/client/lib/stream/queueManager'; @@ -26,22 +26,21 @@ const emptyContext = { const useOmnichannelInquiries = (): Array => { const uid = useUserId(); - const isOmnichannelManger = useRole('livechat-manager'); const omnichannelPoolMaxIncoming = useSetting('Livechat_guest_pool_max_number_incoming_livechats_displayed') as number; useEffect(() => { const handler = async (): Promise => { - initializeLivechatInquiryStream(uid, isOmnichannelManger); + initializeLivechatInquiryStream(uid); }; (async (): Promise => { - initializeLivechatInquiryStream(uid, isOmnichannelManger); + initializeLivechatInquiryStream(uid); Notifications.onUser('departmentAgentData', handler); })(); return (): void => { Notifications.unUser('departmentAgentData', handler); }; - }, [isOmnichannelManger, uid]); + }, [uid]); return useReactiveValue(useCallback(() => LivechatInquiry.find({ status: 'queued', diff --git a/client/sidebar/sections/Omnichannel.js b/client/sidebar/sections/Omnichannel.js index e17db6bbea9b1..0b76c661d8768 100644 --- a/client/sidebar/sections/Omnichannel.js +++ b/client/sidebar/sections/Omnichannel.js @@ -1,17 +1,20 @@ import React from 'react'; import { Sidebar } from '@rocket.chat/fuselage'; +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import { useToastMessageDispatch } from '../../contexts/ToastMessagesContext'; import { useTranslation } from '../../contexts/TranslationContext'; import { useMethod } from '../../contexts/ServerContext'; import { useOmnichannelShowQueueLink, useOmnichannelAgentAvailable, useOmnichannelQueueLink, useOmnichannelDirectoryLink } from '../../contexts/OmnichannelContext'; const OmnichannelSection = React.memo((props) => { - const method = useMethod('livechat:changeLivechatStatus'); + const changeAgentStatus = useMethod('livechat:changeLivechatStatus'); const t = useTranslation(); const agentAvailable = useOmnichannelAgentAvailable(); const showOmnichannelQueueLink = useOmnichannelShowQueueLink(); const queueLink = useOmnichannelQueueLink(); const directoryLink = useOmnichannelDirectoryLink(); + const dispatchToastMessage = useToastMessageDispatch(); const icon = { title: agentAvailable ? t('Available') : t('Not_Available'), @@ -23,12 +26,20 @@ const OmnichannelSection = React.memo((props) => { title: t('Contact_Center'), icon: 'contact', }; + const handleStatusChange = useMutableCallback(async () => { + try { + await changeAgentStatus(); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + console.log(error); + } + }); return {t('Omnichannel')} {showOmnichannelQueueLink && } - { method(); }}/> + ; diff --git a/client/views/omnichannel/agents/AgentEdit.js b/client/views/omnichannel/agents/AgentEdit.js index 1c15446cbc1c1..5a898703aafbc 100644 --- a/client/views/omnichannel/agents/AgentEdit.js +++ b/client/views/omnichannel/agents/AgentEdit.js @@ -65,8 +65,6 @@ export function AgentEdit({ data, userDepartments, availableDepartments, uid, re useMaxChatsPerAgent = () => {}, } = eeForms; - console.log(eeForms, useMaxChatsPerAgent()); - const { values, handlers, hasUnsavedChanges, commit } = useForm({ departments: initialDepartmentValue, status: statusLivechat, maxChats: 0 }); const { reset: resetMaxChats, @@ -109,7 +107,9 @@ export function AgentEdit({ data, userDepartments, availableDepartments, uid, re }); return - + + + {t('Name')} diff --git a/client/views/omnichannel/agents/AgentInfo.js b/client/views/omnichannel/agents/AgentInfo.js index 22f938a16a335..c3a9a26fe67da 100644 --- a/client/views/omnichannel/agents/AgentInfo.js +++ b/client/views/omnichannel/agents/AgentInfo.js @@ -43,14 +43,18 @@ export const AgentInfo = React.memo(function AgentInfo({ return - + + + {children} - } /> + + } /> + {statusLivechat && <> {t('Livechat_status')} diff --git a/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js b/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js index 7501928aa38dc..5a8aa37d80cc7 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js +++ b/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { FieldGroup, Box } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSubscription } from 'use-subscription'; @@ -23,9 +23,12 @@ const getInitalData = ({ workHours }) => ({ const cleanFunc = () => {}; -const BusinessHoursFormContainer = ({ data, saveRef, onChange }) => { +const BusinessHoursFormContainer = ({ data, saveRef, onChange = () => {} }) => { const forms = useSubscription(formsSubscription); + const [hasChangesMultiple, setHasChangesMultiple] = useState(false); + const [hasChangesTimeZone, setHasChangesTimeZone] = useState(false); + const { useBusinessHoursTimeZone = cleanFunc, useBusinessHoursMultiple = cleanFunc, @@ -45,13 +48,13 @@ const BusinessHoursFormContainer = ({ data, saveRef, onChange }) => { saveRef.current.form = values; useEffect(() => { - onChange(hasUnsavedChanges); + onChange(hasUnsavedChanges || (showMultipleBHForm && hasChangesMultiple) || (showTimezone && hasChangesTimeZone)); }); return - {showMultipleBHForm && MultipleBHForm && } - {showTimezone && TimezoneForm && } + {showMultipleBHForm && MultipleBHForm && } + {showTimezone && TimezoneForm && } ; diff --git a/client/views/omnichannel/businessHours/BusinessHoursPage.js b/client/views/omnichannel/businessHours/BusinessHoursPage.js index 55c2c9198248c..f3a6dacaff9f5 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/BusinessHoursPage.js @@ -22,14 +22,14 @@ const BusinessHoursPage = () => { return - - + - + ; }; diff --git a/client/views/omnichannel/businessHours/BusinessHoursRouter.js b/client/views/omnichannel/businessHours/BusinessHoursRouter.js index 55f9b937039c9..24b989d14cc2b 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursRouter.js +++ b/client/views/omnichannel/businessHours/BusinessHoursRouter.js @@ -28,7 +28,7 @@ const BusinessHoursRouter = () => { }, [context, isSingleBH, router, type]); if ((context === 'edit' && type) || (isSingleBH && (context !== 'edit' || type !== 'default'))) { - return ; + return type ? : null; } if (context === 'new') { diff --git a/client/views/omnichannel/businessHours/EditBusinessHoursPage.js b/client/views/omnichannel/businessHours/EditBusinessHoursPage.js index 260a0a0f6f4c4..535d601c01838 100644 --- a/client/views/omnichannel/businessHours/EditBusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/EditBusinessHoursPage.js @@ -23,7 +23,7 @@ const EditBusinessHoursPage = ({ id, type }) => { const saveData = useRef({ form: {} }); - const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); + const [hasChanges, setHasChanges] = useState(false); const save = useMethod('livechat:saveBusinessHour'); const deleteBH = useMethod('livechat:removeBusinessHour'); @@ -112,7 +112,7 @@ const EditBusinessHoursPage = ({ id, type }) => { {type === 'custom' && } - @@ -121,7 +121,7 @@ const EditBusinessHoursPage = ({ id, type }) => { setHasUnsavedChanges(hasChanges)} /> + onChange={setHasChanges} /> ; }; diff --git a/client/views/omnichannel/businessHours/NewBusinessHoursPage.js b/client/views/omnichannel/businessHours/NewBusinessHoursPage.js index 74199b6e007ad..f23b596916944 100644 --- a/client/views/omnichannel/businessHours/NewBusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/NewBusinessHoursPage.js @@ -1,4 +1,4 @@ -import React, { useRef } from 'react'; +import React, { useRef, useState } from 'react'; import { Button, ButtonGroup } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; @@ -35,6 +35,8 @@ const NewBusinessHoursPage = () => { const t = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); + const [hasChanges, setHasChanges] = useState(false); + const saveData = useRef({ form: {} }); const save = useMethod('livechat:saveBusinessHour'); @@ -83,13 +85,13 @@ const NewBusinessHoursPage = () => { - - + ; }; diff --git a/client/views/omnichannel/customFields/CustomFieldsForm.js b/client/views/omnichannel/customFields/CustomFieldsForm.js index 853f6175a36bd..e7ca1b5b97261 100644 --- a/client/views/omnichannel/customFields/CustomFieldsForm.js +++ b/client/views/omnichannel/customFields/CustomFieldsForm.js @@ -58,7 +58,7 @@ const CustomFieldsForm = ({ values = {}, handlers = {}, className }) => { {t('Validation')} - + ; diff --git a/client/views/room/contextualBar/UserInfo/index.js b/client/views/room/contextualBar/UserInfo/index.js index 740cb2cd899cb..90d68dde1d206 100644 --- a/client/views/room/contextualBar/UserInfo/index.js +++ b/client/views/room/contextualBar/UserInfo/index.js @@ -171,6 +171,7 @@ export const UserInfoWithData = React.memo(function UserInfoWithData({ uid, user nickname, } = user; return { + _id, name: showRealNames ? name : username, username, lastLogin, diff --git a/client/views/room/providers/RoomProvider.tsx b/client/views/room/providers/RoomProvider.tsx index 50776ab538a39..30cf555fbe15c 100644 --- a/client/views/room/providers/RoomProvider.tsx +++ b/client/views/room/providers/RoomProvider.tsx @@ -20,11 +20,16 @@ const RoomProvider = ({ rid, children }: Props): JSX.Element => { const _room = useUserRoom(rid, fields) as unknown as IRoom; const room = uid ? subscription || _room : _room; - room._id = rid; - const context = useMemo(() => ({ - rid, - room: { ...room, name: roomTypes.getRoomName(room.t, room) }, - }), [room, rid]); + const context = useMemo(() => { + if (!room) { + return null; + } + room._id = rid; + return { + rid, + room: { ...room, name: roomTypes.getRoomName(room.t, room) }, + }; + }, [room, rid]); if (!room) { return <>; diff --git a/client/views/room/providers/ToolboxProvider.tsx b/client/views/room/providers/ToolboxProvider.tsx index 6380a3168d822..bc6a790e683cb 100644 --- a/client/views/room/providers/ToolboxProvider.tsx +++ b/client/views/room/providers/ToolboxProvider.tsx @@ -1,5 +1,5 @@ import React, { ReactNode, useContext, useMemo, useState, useCallback, useLayoutEffect } from 'react'; -import { useDebouncedState, useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import { useDebouncedState, useMutableCallback, useSafely } from '@rocket.chat/fuselage-hooks'; import { Handler } from '@rocket.chat/emitter'; import { ToolboxContext } from '../lib/Toolbox/ToolboxContext'; @@ -56,7 +56,7 @@ export const ToolboxProvider = ({ children, room }: { children: ReactNode; room: const allowAnonymousRead = useSetting('Accounts_AllowAnonymousRead'); const uid = useUserId(); const [activeTabBar, setActiveTabBar] = useState<[ToolboxActionConfig|undefined, string?]>([undefined]); - const [list, setList] = useDebouncedState>(new Map(), 5); + const [list, setList] = useSafely(useDebouncedState>(new Map(), 5)); const handleChange = useMutableCallback((fn) => { fn(list); setList((list) => new Map(list)); }); const { listen, actions } = useToolboxActions(room); diff --git a/ee/app/livechat-enterprise/server/business-hour/Multiple.ts b/ee/app/livechat-enterprise/server/business-hour/Multiple.ts index 35b1177712498..6d6a8b6dc94e7 100644 --- a/ee/app/livechat-enterprise/server/business-hour/Multiple.ts +++ b/ee/app/livechat-enterprise/server/business-hour/Multiple.ts @@ -6,7 +6,7 @@ import { } from '../../../../../app/livechat/server/business-hour/AbstractBusinessHour'; import { ILivechatBusinessHour } from '../../../../../definition/ILivechatBusinessHour'; import { LivechatDepartmentRaw } from '../../../../../app/models/server/raw/LivechatDepartment'; -import { LivechatDepartmentAgentsRaw } from '../../../models/server/raw/LivechatDepartmentAgents'; +import { LivechatDepartmentAgentsRaw } from '../../../../../app/models/server/raw/LivechatDepartmentAgents'; import { LivechatDepartment, LivechatDepartmentAgents } from '../../../../../app/models/server/raw'; import { filterBusinessHoursThatMustBeOpened } from '../../../../../app/livechat/server/business-hour/Helper'; import { closeBusinessHour, openBusinessHour, removeBusinessHourByAgentIds } from './Helper'; @@ -19,7 +19,7 @@ interface IBusinessHoursExtraProperties extends ILivechatBusinessHour { export class MultipleBusinessHoursBehavior extends AbstractBusinessHourBehavior implements IBusinessHourBehavior { private DepartmentsRepository: LivechatDepartmentRaw = LivechatDepartment; - private DepartmentsAgentsRepository = LivechatDepartmentAgents as LivechatDepartmentAgentsRaw; + private DepartmentsAgentsRepository: LivechatDepartmentAgentsRaw = LivechatDepartmentAgents; constructor() { super(); diff --git a/ee/app/models/server/index.js b/ee/app/models/server/index.js index 30d5dd386edc0..4c68936741e2a 100644 --- a/ee/app/models/server/index.js +++ b/ee/app/models/server/index.js @@ -13,6 +13,7 @@ import './models/LivechatInquiry'; import './models/Messages'; import './raw/LivechatDepartment'; import './raw/LivechatRooms'; +import './raw/LivechatDepartmentAgents'; export { CannedResponse, diff --git a/ee/app/models/server/raw/LivechatDepartmentAgents.ts b/ee/app/models/server/raw/LivechatDepartmentAgents.ts index c64046c4f4b6e..8c8c4422eb0c9 100644 --- a/ee/app/models/server/raw/LivechatDepartmentAgents.ts +++ b/ee/app/models/server/raw/LivechatDepartmentAgents.ts @@ -1,6 +1,7 @@ -import { LivechatDepartmentAgentsRaw as Raw } from '../../../../../app/models/server/raw/LivechatDepartmentAgents'; +import { LivechatDepartmentAgentsRaw } from '../../../../../app/models/server/raw/LivechatDepartmentAgents'; +import { overwriteClassOnLicense } from '../../../license/server'; -export class LivechatDepartmentAgentsRaw extends Raw { +overwriteClassOnLicense('livechat-enterprise', LivechatDepartmentAgentsRaw, { findAgentsByAgentIdAndBusinessHourId(agentId: string, businessHourId: string): Promise> { const match = { $match: { agentId }, @@ -21,6 +22,7 @@ export class LivechatDepartmentAgentsRaw extends Raw { }; const withBusinessHourId = { $match: { 'departments.businessHourId': businessHourId } }; const project = { $project: { departments: 0 } }; - return this.col.aggregate([match, lookup, unwind, withBusinessHourId, project]).toArray(); - } -} + const model = this as unknown as LivechatDepartmentAgentsRaw; + return model.col.aggregate([match, lookup, unwind, withBusinessHourId, project]).toArray(); + }, +}); diff --git a/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js b/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js index 98efc572e9db0..9280866237a81 100644 --- a/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js +++ b/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js @@ -14,12 +14,15 @@ const getInitialData = (data = {}) => ({ departments: mapDepartments(data.departments), }); -const BusinessHoursMultipleContainer = ({ onChange, data: initialData, className }) => { +const BusinessHoursMultipleContainer = ({ onChange, data: initialData, className, hasChangesAndIsValid = () => {} }) => { const { value: data, phase: state } = useEndpointData('livechat/department'); - const { values, handlers } = useForm(getInitialData(initialData)); + const { values, handlers, hasUnsavedChanges } = useForm(getInitialData(initialData)); + + const { name } = values; onChange(values); + hasChangesAndIsValid(hasUnsavedChanges && !!name); const departmentList = useMemo(() => data && data.departments?.map(({ _id, name }) => [_id, name]), [data]); @@ -59,7 +62,7 @@ export const BusinessHoursMultiple = ({ values = {}, handlers = {}, className, d - {t('Name')} + {t('Name')}* diff --git a/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js b/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js index 19ab8046c31cc..874cc0a1c4205 100644 --- a/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js +++ b/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js @@ -1,14 +1,21 @@ -import React, { useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { SelectFiltered, Field } from '@rocket.chat/fuselage'; -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '../../../../client/contexts/TranslationContext'; import { useTimezoneNameList } from '../../../../client/hooks/useTimezoneNameList'; +import { useForm } from '../../../../client/hooks/useForm'; -const BusinessHoursTimeZone = ({ onChange, data, className }) => { +const getInitialData = (data = {}) => ({ + name: data ?? '', +}); + +const BusinessHoursTimeZone = ({ onChange, data, className, hasChanges = () => {} }) => { const t = useTranslation(); - const [timezone, setTimezone] = useState(data); + const { values, handlers, hasUnsavedChanges } = useForm(getInitialData(data)); + + const { name } = values; + const { handleName } = handlers; const timeZones = useTimezoneNameList(); @@ -17,18 +24,15 @@ const BusinessHoursTimeZone = ({ onChange, data, className }) => { t(name), ]), [t, timeZones]); - const handleChange = useMutableCallback((value) => { - setTimezone(value); - }); - - onChange({ name: timezone }); + onChange({ name }); + hasChanges(hasUnsavedChanges); return {t('Timezone')} - + ; }; diff --git a/ee/client/omnichannel/additionalForms/CustomFieldsAdditionalForm.js b/ee/client/omnichannel/additionalForms/CustomFieldsAdditionalForm.js index 438a36f54ae76..d728bb08933b7 100644 --- a/ee/client/omnichannel/additionalForms/CustomFieldsAdditionalForm.js +++ b/ee/client/omnichannel/additionalForms/CustomFieldsAdditionalForm.js @@ -1,4 +1,4 @@ -import React, { useRef, useCallback, useMemo, useEffect } from 'react'; +import React, { useMemo, useEffect } from 'react'; import { Box, Field, TextInput, ToggleSwitch, Select } from '@rocket.chat/fuselage'; import { useTranslation } from '../../../../client/contexts/TranslationContext'; @@ -15,20 +15,9 @@ const getInitialValues = (data) => ({ const checkInvalidOptions = (value) => value.trim() !== '' && !/^([a-zA-Z0-9-_ ]+)(,\s*[a-zA-Z0-9-_ ]+)*$/i.test(value); const CustomFieldsAdditionalFormContainer = ({ data = {}, state, onChange, className }) => { - const saveData = useRef({}); - const t = useTranslation(); - const onChangeValue = useCallback(({ initialValue, value, key }) => { - const { current } = saveData; - if (JSON.stringify(initialValue) !== JSON.stringify(value)) { - current[key] = value; - } else { - delete current[key]; - } - }, []); - - const { values, handlers, hasUnsavedChanges } = useForm(getInitialValues(data), onChangeValue); + const { values, handlers, hasUnsavedChanges } = useForm(getInitialValues(data)); const errors = useMemo(() => ({ optionsError: checkInvalidOptions(values.options) ? t('error-invalid-value') : undefined, @@ -37,8 +26,8 @@ const CustomFieldsAdditionalFormContainer = ({ data = {}, state, onChange, class const hasError = useMemo(() => !!Object.values(errors).filter(Boolean).length, [errors]); useEffect(() => { - onChange({ data: saveData.current, hasError, hasUnsavedChanges }); - }, [hasError, hasUnsavedChanges, onChange]); + onChange({ data: values, hasError, hasUnsavedChanges }); + }, [hasError, hasUnsavedChanges, onChange, values]); return ; }; diff --git a/ee/client/omnichannel/additionalForms/MaxChatsPerAgentDisplay.js b/ee/client/omnichannel/additionalForms/MaxChatsPerAgentDisplay.js index ec9b970343676..7bc93a96b23aa 100644 --- a/ee/client/omnichannel/additionalForms/MaxChatsPerAgentDisplay.js +++ b/ee/client/omnichannel/additionalForms/MaxChatsPerAgentDisplay.js @@ -1,12 +1,11 @@ import React from 'react'; import { useTranslation } from '../../../../client/contexts/TranslationContext'; -import UserInfo from '../../../../client/views/room/contextualBar/UserInfo'; +import { UserInfo } from '../../../../client/views/room/contextualBar/UserInfo'; const MaxChatsPerAgentDisplay = ({ data: { livechat: { maxNumberSimultaneousChat = '' } = {} } = {} }) => { const t = useTranslation(); - - return <> + return maxNumberSimultaneousChat && <> {t('Max_number_of_chats_per_agent')} {maxNumberSimultaneousChat} ; diff --git a/ee/client/omnichannel/additionalForms/register.js b/ee/client/omnichannel/additionalForms/register.js index 826282275fe1d..73d562733eee0 100644 --- a/ee/client/omnichannel/additionalForms/register.js +++ b/ee/client/omnichannel/additionalForms/register.js @@ -16,7 +16,6 @@ hasLicense('livechat-enterprise').then((enabled) => { registerForm({ useEeTextInput: () => useMemo(() => lazy(() => import('./EeTextInput')), []) }); registerForm({ useDepartmentForwarding: () => useMemo(() => lazy(() => import('./DepartmentForwarding')), []) }); registerForm({ useDepartmentBusinessHours: () => useMemo(() => lazy(() => import('./DepartmentBusinessHours')), []) }); - registerForm({ useCustomFieldsAdditionalForm: () => useMemo(() => lazy(() => import('./CustomFieldsAdditionalForm')), []) }); registerForm({ useBusinessHoursTimeZone: () => useMemo(() => lazy(() => import('./BusinessHoursTimeZone')), []) }); registerForm({ useBusinessHoursMultiple: () => useMemo(() => lazy(() => import('./BusinessHoursMultiple')), []) }); registerForm({ useCurrentChatTags: () => useMemo(() => lazy(() => import('../tags/CurrentChatTags')), []) }); diff --git a/ee/server/services/stream-hub/StreamHub.ts b/ee/server/services/stream-hub/StreamHub.ts index bfa1c64644c92..5ddf3c4b5cd3b 100755 --- a/ee/server/services/stream-hub/StreamHub.ts +++ b/ee/server/services/stream-hub/StreamHub.ts @@ -12,7 +12,7 @@ import { RoomsRaw } from '../../../../app/models/server/raw/Rooms'; import { LoginServiceConfigurationRaw } from '../../../../app/models/server/raw/LoginServiceConfiguration'; import { InstanceStatusRaw } from '../../../../app/models/server/raw/InstanceStatus'; import { IntegrationHistoryRaw } from '../../../../app/models/server/raw/IntegrationHistory'; -import { LivechatDepartmentAgentsRaw } from '../../../app/models/server/raw/LivechatDepartmentAgents'; +import { LivechatDepartmentAgentsRaw } from '../../../../app/models/server/raw/LivechatDepartmentAgents'; import { IntegrationsRaw } from '../../../../app/models/server/raw/Integrations'; import { PermissionsRaw } from '../../../../app/models/server/raw/Permissions'; import { api } from '../../../../server/sdk/api'; diff --git a/package-lock.json b/package-lock.json index 03e82a473db2c..8e6232ef23bfa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Rocket.Chat", - "version": "3.10.0", + "version": "3.10.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5d6f80ba04c89..12a5e85914a73 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.10.0", + "version": "3.10.1", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index cd9fee79c2c86..a47ce922cb57b 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2737,6 +2737,7 @@ "Newer_than_may_not_exceed_Older_than": "\"Newer than\" may not exceed \"Older than\"", "Nickname": "Nickname", "Nickname_Placeholder": "Enter your nickname...", + "No": "No", "No_available_agents_to_transfer": "No available agents to transfer", "No_Canned_Responses": "No Canned Responses", "No_channel_with_name_%s_was_found": "No channel with name \"%s\" was found!", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 19686a3b8d335..d908a228e0554 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -1219,6 +1219,7 @@ "Edit_Tag": "Editar Tag", "Edit_Trigger": "Editar Gatilho", "Edit_Unit": "Editar Unidade", + "Edit_User": "Editar usuário", "edit-message": "Editar mensagem", "edit-message_description": "Permissão para editar uma mensagem dentro de uma sala", "edit-other-user-active-status": "Editar outro status ativo do usuário", @@ -1574,7 +1575,7 @@ "Forward_to_user": "Encaminhar ao usuário", "Free": "Grátis", "Frequently_Used": "Usados frequentemente", - "Friday": "Sexta-Feira", + "Friday": "Sexta-feira", "From": "De", "From_Email": "Email De", "From_email_warning": "Aviso: O campo De está sujeito às configurações do seu servidor de emails.", @@ -2370,6 +2371,7 @@ "Newer_than_may_not_exceed_Older_than": "\"Mais recente que\" não pode exceder \"Mais antigo que\"", "Nickname": "Apelido", "Nickname_Placeholder": "Digite seu apelido...", + "No": "Não", "No_available_agents_to_transfer": "Nenhum agente disponível para transferir", "No_channel_with_name_%s_was_found": "Nenhum canal com nome \"%s\" foi encontrado!", "No_channels_yet": "Você não faz parte de nenhum canal ainda.", @@ -3180,6 +3182,7 @@ "Thursday": "Quinta-feira", "Time_in_seconds": "Tempo em segundos", "Timeouts": "Tempos limite", + "Timezone": "Fuso horário", "Title": "Título", "Title_bar_color": "Cor da barra de título", "Title_bar_color_offline": "Cor da barra de título quando offline", @@ -3229,7 +3232,7 @@ "Triggers": "Gatilhos", "Troubleshoot_Disable_Notifications": "Desativar as notificações", "True": "Sim", - "Tuesday": "terça", + "Tuesday": "Terça-feira", "Turn_OFF": "Desligar", "Turn_ON": "Ligar", "Two Factor Authentication": "Autenticação de dois fatores", diff --git a/server/configuration/accounts_meld.js b/server/configuration/accounts_meld.js index 139b1be0262b5..cb3327388b184 100644 --- a/server/configuration/accounts_meld.js +++ b/server/configuration/accounts_meld.js @@ -39,7 +39,7 @@ Accounts.updateOrCreateUserFromExternalService = function(serviceName, serviceDa verified: true, }; - if (!_.findWhere(user.emails, findQuery)) { + if (user.services?.password && !_.findWhere(user.emails, findQuery)) { Users.resetPasswordAndSetRequirePasswordChange(user._id, true, 'This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password'); } diff --git a/server/lib/compareUserPassword.js b/server/lib/compareUserPassword.js index 34c2fb4c69913..ab50aed6be862 100644 --- a/server/lib/compareUserPassword.js +++ b/server/lib/compareUserPassword.js @@ -7,7 +7,7 @@ import { Accounts } from 'meteor/accounts-base'; */ export function compareUserPassword(user, pass) { if (!user?.services?.password?.bcrypt?.trim()) { - return true; + return false; } if (!pass || (!pass.plain && !pass.sha256)) { diff --git a/server/methods/saveUserPreferences.js b/server/methods/saveUserPreferences.js index c29e2894c3ba4..c6f0bc41f34d5 100644 --- a/server/methods/saveUserPreferences.js +++ b/server/methods/saveUserPreferences.js @@ -50,6 +50,7 @@ Meteor.methods({ desktopNotifications: oldDesktopNotifications, mobileNotifications: oldMobileNotifications, emailNotificationMode: oldEmailNotifications, + audioNotifications: oldAudioNotifications, } = (user.settings && user.settings.preferences) || {}; if (user.settings == null) { @@ -99,7 +100,7 @@ Meteor.methods({ } } - if (settings.audioNotifications && oldEmailNotifications !== settings.audioNotifications) { + if (settings.audioNotifications && oldAudioNotifications !== settings.audioNotifications) { if (settings.audioNotifications === 'default') { Subscriptions.clearNotificationUserPreferences(user._id, 'audioNotifications', 'audioPrefOrigin'); } else {