From 49ea816f5c55cb26e2f990b7cad4ccfec5bbe651 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 25 Aug 2020 09:10:15 -0300 Subject: [PATCH 01/10] [IMPROVEMENT] Show "Chats in Progress" group (#2425) --- app/i18n/locales/en.js | 1 + app/i18n/locales/pt-BR.js | 1 + app/views/RoomsListView/index.js | 17 ++++++++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index ef35a18a7..b5d487493 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -339,6 +339,7 @@ export default { Offline: 'Offline', Oops: 'Oops!', Omnichannel: 'Omnichannel', + Open_Livechats: 'Chats in Progress', Omnichannel_enable_alert: 'You\'re not available on Omnichannel. Would you like to be available?', Onboarding_description: 'A workspace is your team or organization’s space to collaborate. Ask the workspace admin for address to join or create one for your team.', Onboarding_join_workspace: 'Join a workspace', diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js index 792498fc0..5ba23d793 100644 --- a/app/i18n/locales/pt-BR.js +++ b/app/i18n/locales/pt-BR.js @@ -315,6 +315,7 @@ export default { No_available_agents_to_transfer: 'Nenhum agente disponível para transferência', Offline: 'Offline', Omnichannel: 'Omnichannel', + Open_Livechats: 'Bate-papos em Andamento', Omnichannel_enable_alert: 'Você não está disponível no Omnichannel. Você quer ficar disponível?', Oops: 'Ops!', Onboarding_description: 'Workspace é o espaço de colaboração do seu time ou organização. Peça um convite ou o endereço ao seu administrador ou crie uma workspace para o seu time.', diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index 8f75eeb0b..17413540e 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -73,10 +73,12 @@ const DISCUSSIONS_HEADER = 'Discussions'; const CHANNELS_HEADER = 'Channels'; const DM_HEADER = 'Direct_Messages'; const GROUPS_HEADER = 'Private_Groups'; +const OMNICHANNEL_HEADER = 'Open_Livechats'; const QUERY_SIZE = 20; const filterIsUnread = s => (s.unread > 0 || s.alert) && !s.hideUnreadStatus; const filterIsFavorite = s => s.f; +const filterIsOmnichannel = s => s.t === 'l'; const shouldUpdateProps = [ 'searchText', @@ -110,7 +112,8 @@ class RoomsListView extends React.Component { id: PropTypes.string, username: PropTypes.string, token: PropTypes.string, - statusLivechat: PropTypes.string + statusLivechat: PropTypes.string, + roles: PropTypes.object }), server: PropTypes.string, searchText: PropTypes.string, @@ -414,7 +417,8 @@ class RoomsListView extends React.Component { sortBy, showUnread, showFavorites, - groupByType + groupByType, + user } = this.props; const db = database.active; @@ -461,6 +465,13 @@ class RoomsListView extends React.Component { */ const chatsOrder = data.map(item => item.rid); + const isOmnichannelAgent = user?.roles?.includes('livechat-agent'); + if (isOmnichannelAgent) { + const omnichannel = chats.filter(s => filterIsOmnichannel(s)); + chats = chats.filter(s => !filterIsOmnichannel(s)); + tempChats = this.addRoomsGroup(omnichannel, OMNICHANNEL_HEADER, tempChats); + } + // unread if (showUnread) { const unread = chats.filter(s => filterIsUnread(s)); @@ -485,7 +496,7 @@ class RoomsListView extends React.Component { tempChats = this.addRoomsGroup(channels, CHANNELS_HEADER, tempChats); tempChats = this.addRoomsGroup(privateGroup, GROUPS_HEADER, tempChats); tempChats = this.addRoomsGroup(direct, DM_HEADER, tempChats); - } else if (showUnread || showFavorites) { + } else if (showUnread || showFavorites || isOmnichannelAgent) { tempChats = this.addRoomsGroup(chats, CHATS_HEADER, tempChats); } else { tempChats = chats; From 67ecab71697ffb20345382555eddab36c064347d Mon Sep 17 00:00:00 2001 From: Youssef Muhamad Date: Tue, 25 Aug 2020 13:51:49 -0300 Subject: [PATCH 02/10] [NEW] Logout from other logged in locations (#2386) * Logout from other logged in locations * Add UI feedback for the request result * Refactor request to use the proper REST API * Change backgroundColor * I18n Co-authored-by: Diego Mello --- app/i18n/locales/en.js | 6 +++++- app/i18n/locales/pt-BR.js | 6 +++++- app/lib/rocketchat.js | 4 ++++ app/utils/log/events.js | 2 ++ app/views/ProfileView/index.js | 27 ++++++++++++++++++++++++++- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index b5d487493..267a6a4d2 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -631,5 +631,9 @@ export default { After_seconds_set_by_admin: 'After {{seconds}} seconds (set by admin)', Dont_activate: 'Don\'t activate now', Queued_chats: 'Queued chats', - Queue_is_empty: 'Queue is empty' + Queue_is_empty: 'Queue is empty', + Logout_from_other_logged_in_locations: 'Logout from other logged in locations', + You_will_be_logged_out_from_other_locations: 'You\'ll be logged out from other locations.', + Logged_out_of_other_clients_successfully: 'Logged out of other clients successfully', + Logout_failed: 'Logout failed!' }; diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js index 5ba23d793..0216ab843 100644 --- a/app/i18n/locales/pt-BR.js +++ b/app/i18n/locales/pt-BR.js @@ -577,5 +577,9 @@ export default { After_seconds_set_by_admin: 'Após {{seconds}} segundos (Configurado pelo adm)', Dont_activate: 'Não ativar agora', Queued_chats: 'Bate-papos na fila', - Queue_is_empty: 'A fila está vazia' + Queue_is_empty: 'A fila está vazia', + Logout_from_other_logged_in_locations: 'Sair de outros locais logados', + You_will_be_logged_out_from_other_locations: 'Você perderá a sessão de outros clientes', + Logged_out_of_other_clients_successfully: 'Desconectado de outros clientes com sucesso', + Logout_failed: 'Falha ao desconectar!' }; diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 33fb6990a..d21398aad 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -419,6 +419,10 @@ const RocketChat = { return user; }, logout, + logoutOtherLocations() { + const { id: userId } = reduxStore.getState().login.user; + return this.sdk.post('users.removeOtherTokens', { userId }); + }, removeServer, async clearCache({ server }) { try { diff --git a/app/utils/log/events.js b/app/utils/log/events.js index c6d51d7e2..9e1dfc9d6 100644 --- a/app/utils/log/events.js +++ b/app/utils/log/events.js @@ -119,6 +119,8 @@ export default { PROFILE_SAVE_AVATAR_F: 'profile_save_avatar_f', PROFILE_SAVE_CHANGES: 'profile_save_changes', PROFILE_SAVE_CHANGES_F: 'profile_save_changes_f', + PROFILE_LOGOUT_OTHER_LOCATIONS: 'profile_logout_other_locations', + PROFILE_LOGOUT_OTHER_LOCATIONS_F: 'profile_logout_other_locations_f', // SETTINGS VIEW SE_CONTACT_US: 'se_contact_us', diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index 19d718768..7c96c5280 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -13,7 +13,7 @@ import KeyboardView from '../../presentation/KeyboardView'; import sharedStyles from '../Styles'; import styles from './styles'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; -import { showErrorAlert } from '../../utils/info'; +import { showErrorAlert, showConfirmationAlert } from '../../utils/info'; import { LISTENER } from '../../containers/Toast'; import EventEmitter from '../../utils/events'; import RocketChat from '../../lib/rocketchat'; @@ -426,6 +426,23 @@ class ProfileView extends React.Component { } } + logoutOtherLocations = () => { + logEvent(events.PROFILE_LOGOUT_OTHER_LOCATIONS); + showConfirmationAlert({ + message: I18n.t('You_will_be_logged_out_from_other_locations'), + callToAction: I18n.t('Logout'), + onPress: async() => { + try { + await RocketChat.logoutOtherLocations(); + EventEmitter.emit(LISTENER, { message: I18n.t('Logged_out_of_other_clients_successfully') }); + } catch { + logEvent(events.PROFILE_LOGOUT_OTHER_LOCATIONS_F); + EventEmitter.emit(LISTENER, { message: I18n.t('Logout_failed') }); + } + } + }); + } + render() { const { name, username, email, newPassword, avatarUrl, customFields, avatar, saving @@ -552,6 +569,14 @@ class ProfileView extends React.Component { loading={saving} theme={theme} /> +