add: kebab and bottom sheet for omnichannel

This commit is contained in:
Gerzon Z 2022-04-14 12:38:06 -04:00
parent 99ea5d8e2a
commit 8d87401185
4 changed files with 121 additions and 9 deletions

View File

@ -243,6 +243,7 @@
"Forgot_password": "Forgot your password?",
"Forgot_Password": "Forgot Password",
"Forward": "Forward",
"Forward_chat": "Forward chat",
"Forward_Chat": "Forward Chat",
"Forward_to_department": "Forward to department",
"Forward_to_user": "Forward to user",
@ -429,6 +430,7 @@
"resetting_password": "resetting password",
"RESET": "RESET",
"Return": "Return",
"Return_to_waiting_line": "Return to waiting line",
"Review_app_title": "Are you enjoying this app?",
"Review_app_desc": "Give us 5 stars on {{store}}",
"Review_app_yes": "Sure!",

View File

@ -193,6 +193,7 @@ export default {
ROOM_AUDIO_FINISH_F: 'room_audio_finish_f',
ROOM_AUDIO_CANCEL: 'room_audio_cancel',
ROOM_AUDIO_CANCEL_F: 'room_audio_cancel_f',
ROOM_SHOW_MORE_ACTIONS: 'room_show_more_actions',
ROOM_SHOW_BOX_ACTIONS: 'room_show_box_actions',
ROOM_BOX_ACTION_PHOTO: 'room_box_action_photo',
ROOM_BOX_ACTION_PHOTO_F: 'room_box_action_photo_f',

View File

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { dequal } from 'dequal';
import { Observable, Subscription } from 'rxjs';
import { Dispatch } from 'redux';
import { StackNavigationProp } from '@react-navigation/stack';
import * as HeaderButton from '../../containers/HeaderButton';
@ -11,18 +12,27 @@ import { events, logEvent } from '../../utils/log';
import { isTeamRoom } from '../../utils/room';
import { IApplicationState, SubscriptionType, TMessageModel, TSubscriptionModel } from '../../definitions';
import { ChatsStackParamList } from '../../stacks/types';
import { withActionSheet } from '../../containers/ActionSheet';
import i18n from '../../i18n';
import { showConfirmationAlert, showErrorAlert } from '../../utils/info';
import { closeRoom } from '../../actions/room';
import RocketChat from '../../lib/rocketchat';
interface IRightButtonsProps {
userId?: string;
threadsEnabled: boolean;
rid?: string;
rid: string;
t: string;
tmid?: string;
teamId?: string;
isMasterDetail: boolean;
toggleFollowThread: Function;
joined: boolean;
status?: string;
dispatch: Dispatch;
encrypted?: boolean;
showActionSheet: Function; // TODO: Change to proper type
transferLivechatGuestPermission: boolean;
navigation: StackNavigationProp<ChatsStackParamList, 'RoomView'>;
}
@ -31,6 +41,8 @@ interface IRigthButtonsState {
tunread: string[];
tunreadUser: string[];
tunreadGroup: string[];
canReturnQueue: boolean;
canForwardGuest: boolean;
}
class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsState> {
@ -43,12 +55,14 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
isFollowingThread: true,
tunread: [],
tunreadUser: [],
tunreadGroup: []
tunreadGroup: [],
canReturnQueue: false,
canForwardGuest: false
};
}
async componentDidMount() {
const { tmid, rid } = this.props;
const { tmid, rid, t } = this.props;
const db = database.active;
if (tmid) {
try {
@ -67,14 +81,32 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
console.log("Can't find subscription to observe.");
}
}
if (t === 'l') {
const canReturnQueue = await this.canReturnQueue();
const canForwardGuest = await this.canForwardGuest();
this.setState({ canReturnQueue, canForwardGuest });
}
}
componentDidUpdate(prevProps: IRightButtonsProps) {
const { status } = this.props;
if (prevProps.status !== status) {
return false;
}
}
shouldComponentUpdate(nextProps: IRightButtonsProps, nextState: IRigthButtonsState) {
const { isFollowingThread, tunread, tunreadUser, tunreadGroup } = this.state;
const { teamId } = this.props;
const { teamId, status, joined } = this.props;
if (nextProps.teamId !== teamId) {
return true;
}
if (nextProps.status !== status) {
return true;
}
if (nextProps.joined !== joined) {
return true;
}
if (nextState.isFollowingThread !== isFollowingThread) {
return true;
}
@ -157,6 +189,69 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
}
};
canForwardGuest = async () => {
const { transferLivechatGuestPermission, rid } = this.props;
const permissions = await RocketChat.hasPermission([transferLivechatGuestPermission], rid);
return permissions[0];
};
canReturnQueue = async () => {
try {
const { returnQueue } = await RocketChat.getRoutingConfig();
return returnQueue;
} catch {
return false;
}
};
returnLivechat = () => {
const { rid } = this.props;
showConfirmationAlert({
message: i18n.t('Would_you_like_to_return_the_inquiry'),
confirmationText: i18n.t('Yes'),
onPress: async () => {
try {
await RocketChat.returnLivechat(rid);
} catch (e: any) {
showErrorAlert(e.reason, i18n.t('Oops'));
}
}
});
};
closeLivechat = () => {
const { dispatch, rid } = this.props;
dispatch(closeRoom(rid));
};
showMoreActions = () => {
logEvent(events.ROOM_SHOW_MORE_ACTIONS);
const { showActionSheet, rid, navigation } = this.props;
const { canReturnQueue, canForwardGuest } = this.state;
const options = [
canForwardGuest && {
title: i18n.t('Forward_Chat'),
icon: 'chat-forward',
onPress: () => navigation.navigate('ForwardLivechatView', { rid })
},
canReturnQueue && {
title: i18n.t('Return_to_waiting_line'),
icon: 'move-to-the-queue',
onPress: () => this.returnLivechat()
},
{
title: i18n.t('Close'),
icon: 'chat-close',
onPress: () => this.closeLivechat(),
danger: true
}
];
showActionSheet({ options });
};
goSearchView = () => {
logEvent(events.ROOM_GO_SEARCH);
const { rid, t, navigation, isMasterDetail, encrypted } = this.props;
@ -185,8 +280,17 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
render() {
const { isFollowingThread, tunread, tunreadUser, tunreadGroup } = this.state;
const { t, tmid, threadsEnabled, teamId, joined } = this.props;
const { t, tmid, threadsEnabled, teamId, joined, status } = this.props;
const isOmnichannelPreview = joined && status !== 'queued';
if (t === 'l') {
if (isOmnichannelPreview) {
return (
<HeaderButton.Container>
<HeaderButton.Item iconName='kebab' onPress={this.showMoreActions} testID='room-view-header-omnichannel-kebab' />
</HeaderButton.Container>
);
}
return null;
}
if (tmid) {
@ -222,7 +326,8 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS
const mapStateToProps = (state: IApplicationState) => ({
userId: getUserSelector(state).id,
threadsEnabled: state.settings.Threads_enabled as boolean,
isMasterDetail: state.app.isMasterDetail
isMasterDetail: state.app.isMasterDetail,
transferLivechatGuestPermission: state.permissions['transfer-livechat-guest']
});
export default connect(mapStateToProps)(RightButtonsContainer);
export default connect(mapStateToProps)(withActionSheet(RightButtonsContainer));

View File

@ -115,7 +115,8 @@ const roomAttrsUpdate = [
'visitor',
'joinCodeRequired',
'teamMain',
'teamId'
'teamId',
'status'
] as const;
interface IRoomViewProps extends IBaseScreen<ChatsStackParamList, 'RoomView'> {
@ -142,7 +143,9 @@ type TRoomUpdate = typeof roomAttrsUpdate[number];
interface IRoomViewState {
[key: string]: any;
joined: boolean;
room: TSubscriptionModel | { rid: string; t: string; name?: string; fname?: string; prid?: string; joinCodeRequired?: boolean };
room:
| TSubscriptionModel
| { rid: string; t: string; name?: string; fname?: string; prid?: string; joinCodeRequired?: boolean; status?: boolean };
roomUpdate: {
[K in TRoomUpdate]?: any; // TODO: get type from TSubscriptionModel
};
@ -512,6 +515,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
tmid={tmid}
teamId={teamId}
joined={joined}
status={room.status}
t={this.t || t}
encrypted={encrypted}
navigation={navigation}