[IMPROVEMENT] Verify Enterprise status on Omnichannel (#2399)
* Add enterpriseModules on Redux * Fetch enterprise modules and put on redux * hasLicense * Clear modules * Hide omnichannel rooms * Minor refactor * Hide omnichannel toggle * Check license on user status * Apply on search * lint * Look for 'livechat-enterprise' * One module is enough to enable the features * Unhide omnichannel rooms * Sort tweaks * Move omnichannel toggle to RoomsListView * Remove omnichannel toggle from SettingsView * Fix toggle * Ask to enable omnichannel * Lint * Fix issues found on review
This commit is contained in:
parent
54c4614e2e
commit
b06bf7fcb5
|
@ -66,3 +66,4 @@ export const INVITE_LINKS = createRequestTypes('INVITE_LINKS', [
|
|||
]);
|
||||
export const SETTINGS = createRequestTypes('SETTINGS', ['CLEAR', 'ADD']);
|
||||
export const APP_STATE = createRequestTypes('APP_STATE', ['FOREGROUND', 'BACKGROUND']);
|
||||
export const ENTERPRISE_MODULES = createRequestTypes('ENTERPRISE_MODULES', ['CLEAR', 'SET']);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { ENTERPRISE_MODULES } from './actionsTypes';
|
||||
|
||||
export function setEnterpriseModules(modules) {
|
||||
return {
|
||||
type: ENTERPRISE_MODULES.SET,
|
||||
payload: modules
|
||||
};
|
||||
}
|
||||
|
||||
export function clearEnterpriseModules() {
|
||||
return {
|
||||
type: ENTERPRISE_MODULES.CLEAR
|
||||
};
|
||||
}
|
|
@ -339,6 +339,7 @@ export default {
|
|||
Offline: 'Offline',
|
||||
Oops: 'Oops!',
|
||||
Omnichannel: 'Omnichannel',
|
||||
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',
|
||||
Onboarding_subtitle: 'Beyond Team Collaboration',
|
||||
|
|
|
@ -314,6 +314,8 @@ export default {
|
|||
Not_RC_Server: 'Este não é um servidor Rocket.Chat.\n{{contact}}',
|
||||
No_available_agents_to_transfer: 'Nenhum agente disponível para transferência',
|
||||
Offline: 'Offline',
|
||||
Omnichannel: 'Omnichannel',
|
||||
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.',
|
||||
Onboarding_join_workspace: 'Entre numa workspace',
|
||||
|
|
|
@ -27,4 +27,6 @@ export default class Server extends Model {
|
|||
@field('biometry') biometry;
|
||||
|
||||
@field('unique_id') uniqueID;
|
||||
|
||||
@field('enterprise_modules') enterpriseModules;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,17 @@ export default schemaMigrations({
|
|||
]
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
toVersion: 6,
|
||||
steps: [
|
||||
addColumns({
|
||||
table: 'servers',
|
||||
columns: [
|
||||
{ name: 'enterprise_modules', type: 'string', isOptional: true }
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { appSchema, tableSchema } from '@nozbe/watermelondb';
|
||||
|
||||
export default appSchema({
|
||||
version: 5,
|
||||
version: 6,
|
||||
tables: [
|
||||
tableSchema({
|
||||
name: 'users',
|
||||
|
@ -29,7 +29,8 @@ export default appSchema({
|
|||
{ name: 'auto_lock', type: 'boolean', isOptional: true },
|
||||
{ name: 'auto_lock_time', type: 'number', isOptional: true },
|
||||
{ name: 'biometry', type: 'boolean', isOptional: true },
|
||||
{ name: 'unique_id', type: 'string', isOptional: true }
|
||||
{ name: 'unique_id', type: 'string', isOptional: true },
|
||||
{ name: 'enterprise_modules', type: 'string', isOptional: true }
|
||||
]
|
||||
})
|
||||
]
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import semver from 'semver';
|
||||
|
||||
import reduxStore from '../createStore';
|
||||
import database from '../database';
|
||||
import log from '../../utils/log';
|
||||
import { setEnterpriseModules as setEnterpriseModulesAction, clearEnterpriseModules } from '../../actions/enterpriseModules';
|
||||
|
||||
export const LICENSE_OMNICHANNEL_MOBILE_ENTERPRISE = 'omnichannel-mobile-enterprise';
|
||||
export const LICENSE_LIVECHAT_ENTERPRISE = 'livechat-enterprise';
|
||||
|
||||
export async function setEnterpriseModules() {
|
||||
try {
|
||||
const { server: serverId } = reduxStore.getState().server;
|
||||
const serversDB = database.servers;
|
||||
const serversCollection = serversDB.collections.get('servers');
|
||||
const server = await serversCollection.find(serverId);
|
||||
if (server.enterpriseModules) {
|
||||
reduxStore.dispatch(setEnterpriseModulesAction(server.enterpriseModules.split(',')));
|
||||
return;
|
||||
}
|
||||
reduxStore.dispatch(clearEnterpriseModules());
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
||||
|
||||
export function getEnterpriseModules() {
|
||||
return new Promise(async(resolve) => {
|
||||
try {
|
||||
const { version: serverVersion, server: serverId } = reduxStore.getState().server;
|
||||
if (serverVersion && semver.gte(semver.coerce(serverVersion), '3.1.0')) {
|
||||
// RC 3.1.0
|
||||
const enterpriseModules = await this.methodCallWrapper('license:getModules');
|
||||
if (enterpriseModules) {
|
||||
const serversDB = database.servers;
|
||||
const serversCollection = serversDB.collections.get('servers');
|
||||
const server = await serversCollection.find(serverId);
|
||||
await serversDB.action(async() => {
|
||||
await server.update((s) => {
|
||||
s.enterpriseModules = enterpriseModules.join(',');
|
||||
});
|
||||
});
|
||||
reduxStore.dispatch(setEnterpriseModulesAction(enterpriseModules));
|
||||
return resolve();
|
||||
}
|
||||
}
|
||||
reduxStore.dispatch(clearEnterpriseModules());
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
||||
export function hasLicense(module) {
|
||||
const { enterpriseModules } = reduxStore.getState();
|
||||
return enterpriseModules.includes(module);
|
||||
}
|
||||
|
||||
export function isOmnichannelModuleAvailable() {
|
||||
const { enterpriseModules } = reduxStore.getState();
|
||||
return [LICENSE_OMNICHANNEL_MOBILE_ENTERPRISE, LICENSE_LIVECHAT_ENTERPRISE].some(module => enterpriseModules.includes(module));
|
||||
}
|
|
@ -244,7 +244,9 @@ export default function subscribeRooms() {
|
|||
const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||
if (/userData/.test(ev)) {
|
||||
const [{ diff }] = ddpMessage.fields.args;
|
||||
store.dispatch(setUser({ statusLivechat: diff?.statusLivechat }));
|
||||
if (diff?.statusLivechat) {
|
||||
store.dispatch(setUser({ statusLivechat: diff.statusLivechat }));
|
||||
}
|
||||
}
|
||||
if (/subscriptions/.test(ev)) {
|
||||
if (type === 'removed') {
|
||||
|
|
|
@ -29,6 +29,9 @@ import getSettings, { getLoginSettings, setSettings } from './methods/getSetting
|
|||
import getRooms from './methods/getRooms';
|
||||
import getPermissions from './methods/getPermissions';
|
||||
import { getCustomEmojis, setCustomEmojis } from './methods/getCustomEmojis';
|
||||
import {
|
||||
getEnterpriseModules, setEnterpriseModules, hasLicense, isOmnichannelModuleAvailable
|
||||
} from './methods/enterpriseModules';
|
||||
import getSlashCommands from './methods/getSlashCommands';
|
||||
import getRoles from './methods/getRoles';
|
||||
import canOpenRoom from './methods/canOpenRoom';
|
||||
|
@ -519,6 +522,7 @@ const RocketChat = {
|
|||
} else if (!filterUsers && filterRooms) {
|
||||
data = data.filter(item => item.t !== 'd' || RocketChat.isGroupChat(item));
|
||||
}
|
||||
|
||||
data = data.slice(0, 7);
|
||||
|
||||
data = data.map((sub) => {
|
||||
|
@ -620,6 +624,10 @@ const RocketChat = {
|
|||
getPermissions,
|
||||
getCustomEmojis,
|
||||
setCustomEmojis,
|
||||
getEnterpriseModules,
|
||||
setEnterpriseModules,
|
||||
hasLicense,
|
||||
isOmnichannelModuleAvailable,
|
||||
getSlashCommands,
|
||||
getRoles,
|
||||
parseSettings: settings => settings.reduce((ret, item) => {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { ENTERPRISE_MODULES } from '../actions/actionsTypes';
|
||||
|
||||
const initialState = [];
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case ENTERPRISE_MODULES.SET:
|
||||
return action.payload;
|
||||
case ENTERPRISE_MODULES.CLEAR:
|
||||
return initialState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
|
@ -17,6 +17,7 @@ import usersTyping from './usersTyping';
|
|||
import inviteLinks from './inviteLinks';
|
||||
import createDiscussion from './createDiscussion';
|
||||
import inquiry from './inquiry';
|
||||
import enterpriseModules from './enterpriseModules';
|
||||
|
||||
export default combineReducers({
|
||||
settings,
|
||||
|
@ -36,5 +37,6 @@ export default combineReducers({
|
|||
usersTyping,
|
||||
inviteLinks,
|
||||
createDiscussion,
|
||||
inquiry
|
||||
inquiry,
|
||||
enterpriseModules
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
loginFailure, loginSuccess, setUser, logout
|
||||
} from '../actions/login';
|
||||
import { roomsRequest } from '../actions/rooms';
|
||||
import { inquiryRequest } from '../actions/inquiry';
|
||||
import { inquiryRequest, inquiryReset } from '../actions/inquiry';
|
||||
import { toMomentLocale } from '../utils/moment';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import log, { logEvent, events } from '../utils/log';
|
||||
|
@ -85,6 +85,14 @@ const fetchUsersPresence = function* fetchUserPresence() {
|
|||
RocketChat.subscribeUsersPresence();
|
||||
};
|
||||
|
||||
const fetchEnterpriseModules = function* fetchEnterpriseModules({ user }) {
|
||||
yield RocketChat.getEnterpriseModules();
|
||||
|
||||
if (user && user.statusLivechat === 'available' && RocketChat.isOmnichannelModuleAvailable()) {
|
||||
yield put(inquiryRequest());
|
||||
}
|
||||
};
|
||||
|
||||
const handleLoginSuccess = function* handleLoginSuccess({ user }) {
|
||||
try {
|
||||
const adding = yield select(state => state.server.adding);
|
||||
|
@ -94,13 +102,13 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
|
|||
|
||||
const server = yield select(getServer);
|
||||
yield put(roomsRequest());
|
||||
yield put(inquiryRequest());
|
||||
yield fork(fetchPermissions);
|
||||
yield fork(fetchCustomEmojis);
|
||||
yield fork(fetchRoles);
|
||||
yield fork(fetchSlashCommands);
|
||||
yield fork(registerPushToken);
|
||||
yield fork(fetchUsersPresence);
|
||||
yield fork(fetchEnterpriseModules, { user });
|
||||
|
||||
I18n.locale = user.language;
|
||||
moment.locale(toMomentLocale(user.language));
|
||||
|
@ -210,8 +218,12 @@ const handleSetUser = function* handleSetUser({ user }) {
|
|||
yield put(setActiveUsers({ [userId]: user }));
|
||||
}
|
||||
|
||||
if (user && user.statusLivechat) {
|
||||
if (user?.statusLivechat && RocketChat.isOmnichannelModuleAvailable()) {
|
||||
if (user.statusLivechat === 'available') {
|
||||
yield put(inquiryRequest());
|
||||
} else {
|
||||
yield put(inquiryReset());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
|
|||
// and block the selectServerSuccess raising multiples errors
|
||||
RocketChat.setSettings();
|
||||
RocketChat.setCustomEmojis();
|
||||
RocketChat.setEnterpriseModules();
|
||||
|
||||
let serverInfo;
|
||||
if (fetchVersion) {
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
import React, { memo, useState, useEffect } from 'react';
|
||||
import {
|
||||
View, Text, StyleSheet, Switch
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Touch from '../../../utils/touch';
|
||||
import { CustomIcon } from '../../../lib/Icons';
|
||||
import I18n from '../../../i18n';
|
||||
import styles from '../styles';
|
||||
import { themes, SWITCH_TRACK_COLOR } from '../../../constants/colors';
|
||||
import { withTheme } from '../../../theme';
|
||||
import UnreadBadge from '../../../presentation/UnreadBadge';
|
||||
import RocketChat from '../../../lib/rocketchat';
|
||||
|
||||
const OmnichannelStatus = memo(({
|
||||
searching, goQueue, theme, queueSize, inquiryEnabled, user
|
||||
}) => {
|
||||
if (searching > 0 || !(RocketChat.isOmnichannelModuleAvailable() && user?.roles?.includes('livechat-agent'))) {
|
||||
return null;
|
||||
}
|
||||
const [status, setStatus] = useState(user?.statusLivechat === 'available');
|
||||
|
||||
useEffect(() => {
|
||||
setStatus(user.statusLivechat === 'available');
|
||||
}, [user.statusLivechat]);
|
||||
|
||||
const toggleLivechat = async() => {
|
||||
try {
|
||||
setStatus(v => !v);
|
||||
await RocketChat.changeLivechatStatus();
|
||||
} catch {
|
||||
setStatus(v => !v);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Touch
|
||||
onPress={goQueue}
|
||||
theme={theme}
|
||||
style={{ backgroundColor: themes[theme].headerSecondaryBackground }}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.dropdownContainerHeader,
|
||||
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor }
|
||||
]}
|
||||
>
|
||||
<CustomIcon style={[styles.queueIcon, { color: themes[theme].auxiliaryText }]} size={22} name='omnichannel' />
|
||||
<Text style={[styles.queueToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Omnichannel')}</Text>
|
||||
{inquiryEnabled
|
||||
? (
|
||||
<UnreadBadge
|
||||
style={styles.queueIcon}
|
||||
unread={queueSize}
|
||||
theme={theme}
|
||||
/>
|
||||
)
|
||||
: null}
|
||||
<Switch
|
||||
style={styles.omnichannelToggle}
|
||||
value={status}
|
||||
trackColor={SWITCH_TRACK_COLOR}
|
||||
onValueChange={toggleLivechat}
|
||||
/>
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
});
|
||||
|
||||
OmnichannelStatus.propTypes = {
|
||||
searching: PropTypes.bool,
|
||||
goQueue: PropTypes.func,
|
||||
queueSize: PropTypes.number,
|
||||
inquiryEnabled: PropTypes.bool,
|
||||
theme: PropTypes.string,
|
||||
user: PropTypes.shape({
|
||||
roles: PropTypes.array,
|
||||
statusLivechat: PropTypes.string
|
||||
})
|
||||
};
|
||||
|
||||
export default withTheme(OmnichannelStatus);
|
|
@ -1,49 +0,0 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Touch from '../../../utils/touch';
|
||||
import I18n from '../../../i18n';
|
||||
import styles from '../styles';
|
||||
import { themes } from '../../../constants/colors';
|
||||
import { withTheme } from '../../../theme';
|
||||
import UnreadBadge from '../../../presentation/UnreadBadge';
|
||||
|
||||
const Queue = React.memo(({
|
||||
searching, goQueue, queueSize, inquiryEnabled, theme
|
||||
}) => {
|
||||
if (searching > 0 || !inquiryEnabled) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Touch
|
||||
onPress={goQueue}
|
||||
theme={theme}
|
||||
style={{ backgroundColor: themes[theme].headerSecondaryBackground }}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.dropdownContainerHeader,
|
||||
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor }
|
||||
]}
|
||||
>
|
||||
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Queued_chats')}</Text>
|
||||
<UnreadBadge
|
||||
style={styles.sortIcon}
|
||||
unread={queueSize}
|
||||
theme={theme}
|
||||
/>
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
});
|
||||
|
||||
Queue.propTypes = {
|
||||
searching: PropTypes.bool,
|
||||
goQueue: PropTypes.func,
|
||||
queueSize: PropTypes.number,
|
||||
inquiryEnabled: PropTypes.bool,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default withTheme(Queue);
|
|
@ -28,8 +28,8 @@ const Sort = React.memo(({
|
|||
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor }
|
||||
]}
|
||||
>
|
||||
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort' />
|
||||
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
|
||||
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort-az' />
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Queue from './Queue';
|
||||
import Sort from './Sort';
|
||||
import OmnichannelStatus from './OmnichannelStatus';
|
||||
|
||||
const ListHeader = React.memo(({
|
||||
searching,
|
||||
|
@ -10,11 +10,12 @@ const ListHeader = React.memo(({
|
|||
toggleSort,
|
||||
goQueue,
|
||||
queueSize,
|
||||
inquiryEnabled
|
||||
inquiryEnabled,
|
||||
user
|
||||
}) => (
|
||||
<>
|
||||
<Sort searching={searching} sortBy={sortBy} toggleSort={toggleSort} />
|
||||
<Queue searching={searching} goQueue={goQueue} queueSize={queueSize} inquiryEnabled={inquiryEnabled} />
|
||||
<OmnichannelStatus searching={searching} goQueue={goQueue} inquiryEnabled={inquiryEnabled} queueSize={queueSize} user={user} />
|
||||
</>
|
||||
));
|
||||
|
||||
|
@ -24,7 +25,8 @@ ListHeader.propTypes = {
|
|||
toggleSort: PropTypes.func,
|
||||
goQueue: PropTypes.func,
|
||||
queueSize: PropTypes.number,
|
||||
inquiryEnabled: PropTypes.bool
|
||||
inquiryEnabled: PropTypes.bool,
|
||||
user: PropTypes.object
|
||||
};
|
||||
|
||||
export default ListHeader;
|
||||
|
|
|
@ -156,8 +156,8 @@ class Sort extends PureComponent {
|
|||
>
|
||||
<View style={[styles.dropdownContainerHeader, { borderColor: themes[theme].separatorColor }]}>
|
||||
<View style={styles.sortItemContainer}>
|
||||
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort' />
|
||||
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
|
||||
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort-az' />
|
||||
</View>
|
||||
</View>
|
||||
</Touch>
|
||||
|
|
|
@ -62,7 +62,7 @@ import { goRoom } from '../../utils/goRoom';
|
|||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import Header, { getHeaderTitlePosition } from '../../containers/Header';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
import { showErrorAlert } from '../../utils/info';
|
||||
import { showErrorAlert, showConfirmationAlert } from '../../utils/info';
|
||||
import { getInquiryQueueSelector } from '../../selectors/inquiry';
|
||||
|
||||
const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
|
||||
|
@ -109,7 +109,8 @@ class RoomsListView extends React.Component {
|
|||
user: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
username: PropTypes.string,
|
||||
token: PropTypes.string
|
||||
token: PropTypes.string,
|
||||
statusLivechat: PropTypes.string
|
||||
}),
|
||||
server: PropTypes.string,
|
||||
searchText: PropTypes.string,
|
||||
|
@ -450,7 +451,6 @@ class RoomsListView extends React.Component {
|
|||
.observe();
|
||||
}
|
||||
|
||||
|
||||
this.querySubscription = observable.subscribe((data) => {
|
||||
let tempChats = [];
|
||||
let chats = data;
|
||||
|
@ -685,7 +685,28 @@ class RoomsListView extends React.Component {
|
|||
|
||||
goQueue = () => {
|
||||
logEvent(events.RL_GO_QUEUE);
|
||||
const { navigation, isMasterDetail, queueSize } = this.props;
|
||||
const {
|
||||
navigation, isMasterDetail, queueSize, inquiryEnabled, user
|
||||
} = this.props;
|
||||
|
||||
// if not-available, prompt to change to available
|
||||
if (user?.statusLivechat !== 'available') {
|
||||
showConfirmationAlert({
|
||||
message: I18n.t('Omnichannel_enable_alert'),
|
||||
callToAction: I18n.t('Yes'),
|
||||
onPress: async() => {
|
||||
try {
|
||||
await RocketChat.changeLivechatStatus();
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!inquiryEnabled) {
|
||||
return;
|
||||
}
|
||||
// prevent navigation to empty list
|
||||
if (!queueSize) {
|
||||
return showErrorAlert(I18n.t('Queue_is_empty'), I18n.t('Oops'));
|
||||
|
@ -813,7 +834,9 @@ class RoomsListView extends React.Component {
|
|||
|
||||
renderListHeader = () => {
|
||||
const { searching } = this.state;
|
||||
const { sortBy, queueSize, inquiryEnabled } = this.props;
|
||||
const {
|
||||
sortBy, queueSize, inquiryEnabled, user
|
||||
} = this.props;
|
||||
return (
|
||||
<ListHeader
|
||||
searching={searching}
|
||||
|
@ -823,6 +846,7 @@ class RoomsListView extends React.Component {
|
|||
goQueue={this.goQueue}
|
||||
queueSize={queueSize}
|
||||
inquiryEnabled={inquiryEnabled}
|
||||
user={user}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -23,7 +23,11 @@ export default StyleSheet.create({
|
|||
sortToggleText: {
|
||||
fontSize: 16,
|
||||
flex: 1,
|
||||
marginLeft: 12,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
queueToggleText: {
|
||||
fontSize: 16,
|
||||
flex: 1,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
dropdownContainer: {
|
||||
|
@ -58,6 +62,11 @@ export default StyleSheet.create({
|
|||
height: 22,
|
||||
marginHorizontal: 12
|
||||
},
|
||||
queueIcon: {
|
||||
width: 22,
|
||||
height: 22,
|
||||
marginHorizontal: 12
|
||||
},
|
||||
groupTitleContainer: {
|
||||
paddingHorizontal: 12,
|
||||
paddingTop: 17,
|
||||
|
@ -116,5 +125,8 @@ export default StyleSheet.create({
|
|||
serverSeparator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
marginLeft: 72
|
||||
},
|
||||
omnichannelToggle: {
|
||||
marginRight: 12
|
||||
}
|
||||
});
|
||||
|
|
|
@ -36,7 +36,6 @@ import { LISTENER } from '../../containers/Toast';
|
|||
import EventEmitter from '../../utils/events';
|
||||
import { appStart as appStartAction, ROOT_LOADING } from '../../actions/app';
|
||||
import { onReviewPress } from '../../utils/review';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
|
||||
const SectionSeparator = React.memo(({ theme }) => (
|
||||
|
@ -73,20 +72,9 @@ class SettingsView extends React.Component {
|
|||
isMasterDetail: PropTypes.bool,
|
||||
logout: PropTypes.func.isRequired,
|
||||
selectServerRequest: PropTypes.func,
|
||||
user: PropTypes.shape({
|
||||
roles: PropTypes.array,
|
||||
statusLivechat: PropTypes.string
|
||||
}),
|
||||
appStart: PropTypes.func
|
||||
}
|
||||
|
||||
get showLivechat() {
|
||||
const { user } = this.props;
|
||||
const { roles } = user;
|
||||
|
||||
return roles?.includes('livechat-agent');
|
||||
}
|
||||
|
||||
handleLogout = () => {
|
||||
logEvent(events.SE_LOG_OUT);
|
||||
showConfirmationAlert({
|
||||
|
@ -131,14 +119,6 @@ class SettingsView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
toggleLivechat = async() => {
|
||||
try {
|
||||
await RocketChat.changeLivechatStatus();
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
navigateToScreen = (screen) => {
|
||||
logEvent(events[`SE_GO_${ screen.replace('View', '').toUpperCase() }`]);
|
||||
const { navigation } = this.props;
|
||||
|
@ -204,18 +184,6 @@ class SettingsView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
renderLivechatSwitch = () => {
|
||||
const { user } = this.props;
|
||||
const { statusLivechat } = user;
|
||||
return (
|
||||
<Switch
|
||||
value={statusLivechat === 'available'}
|
||||
trackColor={SWITCH_TRACK_COLOR}
|
||||
onValueChange={this.toggleLivechat}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { server, isMasterDetail, theme } = this.props;
|
||||
return (
|
||||
|
@ -336,18 +304,6 @@ class SettingsView extends React.Component {
|
|||
|
||||
<SectionSeparator theme={theme} />
|
||||
|
||||
{this.showLivechat ? (
|
||||
<>
|
||||
<ListItem
|
||||
title={I18n.t('Omnichannel')}
|
||||
testID='settings-view-livechat'
|
||||
right={() => this.renderLivechatSwitch()}
|
||||
theme={theme}
|
||||
/>
|
||||
<SectionSeparator theme={theme} />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Send_crash_report')}
|
||||
testID='settings-view-crash-report'
|
||||
|
@ -387,7 +343,6 @@ class SettingsView extends React.Component {
|
|||
|
||||
const mapStateToProps = state => ({
|
||||
server: state.server,
|
||||
user: getUserSelector(state),
|
||||
allowCrashReport: state.crashReport.allowCrashReport,
|
||||
isMasterDetail: state.app.isMasterDetail
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue