diff --git a/app/ee/omnichannel/containers/CloseLivechatSheet/index.tsx b/app/ee/omnichannel/containers/CloseLivechatSheet/index.tsx
deleted file mode 100644
index d1a03121a..000000000
--- a/app/ee/omnichannel/containers/CloseLivechatSheet/index.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-
-import ActionSheetContentWithInputAndSubmit from '../../../../containers/ActionSheet/ActionSheetContentWithInputAndSubmit';
-import I18n from '../../../../i18n';
-
-const CloseLivechatSheet = ({
- onSubmit = () => {},
- onCancel = () => {}
-}: {
- onSubmit: (comment: string) => void;
- onCancel: () => void;
-}) => (
-
-);
-
-export default CloseLivechatSheet;
diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json
index fd5b85696..187264989 100644
--- a/app/i18n/locales/en.json
+++ b/app/i18n/locales/en.json
@@ -840,5 +840,7 @@
"Show_badge_for_mentions": "Show badge for mentions",
"Show_badge_for_mentions_Info": "Display badge for direct mentions only",
"error-init-video-conf": "Error starting video call",
- "totp-invalid": "Code or password invalid"
+ "totp-invalid": "Code or password invalid",
+ "Close_Chat": "Close Chat",
+ "Select_tags": "Select tags"
}
\ No newline at end of file
diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json
index ef59e82d8..020de9326 100644
--- a/app/i18n/locales/pt-BR.json
+++ b/app/i18n/locales/pt-BR.json
@@ -793,5 +793,7 @@
"Mark_as_unread_Info": "Mostrar sala como não lida quando houver mensagens não lidas",
"Show_badge_for_mentions": "Mostrar contador para menções",
"Show_badge_for_mentions_Info": "Mostrar contador somente para menções diretas",
- "totp-invalid": "Código ou senha inválida"
+ "totp-invalid": "Código ou senha inválida",
+ "Close_Chat": "Fechar Conversa",
+ "Select_tags": "Selecionar tag(s)"
}
\ No newline at end of file
diff --git a/app/lib/methods/helpers/closeLivechat.ts b/app/lib/methods/helpers/closeLivechat.ts
index cff8a8a2b..ff49a0a66 100644
--- a/app/lib/methods/helpers/closeLivechat.ts
+++ b/app/lib/methods/helpers/closeLivechat.ts
@@ -7,14 +7,16 @@ import log from './log';
export const closeLivechat = async ({
rid,
comment,
- isMasterDetail
+ isMasterDetail,
+ tags
}: {
rid: string;
isMasterDetail: boolean;
comment?: string;
+ tags?: string[];
}) => {
try {
- await Services.closeLivechat(rid, comment);
+ await Services.closeLivechat(rid, comment, tags);
if (isMasterDetail) {
Navigation.navigate('DrawerNavigator');
} else {
diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts
index cb97af0ac..27c72d048 100644
--- a/app/lib/services/restApi.ts
+++ b/app/lib/services/restApi.ts
@@ -18,6 +18,7 @@ import { getDeviceToken } from '../notifications';
import { RoomTypes, roomTypeToApiType, unsubscribeRooms } from '../methods';
import sdk from './sdk';
import { compareServerVersion, getBundleId, isIOS } from '../methods/helpers';
+import { ILivechatTag } from '../../definitions/ILivechatTag';
export const createChannel = ({
name,
@@ -347,9 +348,15 @@ export const getTeamListRoom = ({
return sdk.get('teams.listRooms', params);
};
-export const closeLivechat = (rid: string, comment?: string) =>
+export const closeLivechat = (rid: string, comment?: string, tags?: string[]) => {
+ // RC 3.2.0
+ let params;
+ if (tags && tags?.length) {
+ params = { tags };
+ }
// RC 0.29.0
- sdk.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true });
+ return sdk.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true, ...params });
+};
export const editLivechat = (userData: TParams, roomData: TParams): Promise<{ error?: string }> =>
// RC 0.55.0
@@ -398,13 +405,7 @@ export const getRoutingConfig = (): Promise<{
// RC 2.0.0
sdk.methodCallWrapper('livechat:getRoutingConfig');
-export const getTagsList = (): Promise<
- {
- _id: string;
- name: string;
- departments: string[];
- }[]
-> =>
+export const getTagsList = (): Promise =>
// RC 2.0.0
sdk.methodCallWrapper('livechat:getTagsList');
diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx
index 6a525d575..ea17fee27 100644
--- a/app/stacks/InsideStack.tsx
+++ b/app/stacks/InsideStack.tsx
@@ -22,6 +22,7 @@ import AutoTranslateView from '../views/AutoTranslateView';
import DirectoryView from '../views/DirectoryView';
import NotificationPrefView from '../views/NotificationPreferencesView';
import ForwardLivechatView from '../views/ForwardLivechatView';
+import CloseLivechatView from '../views/CloseLivechatView';
import LivechatEditView from '../views/LivechatEditView';
import PickerView from '../views/PickerView';
import ThreadMessagesView from '../views/ThreadMessagesView';
@@ -116,6 +117,7 @@ const ChatsStackNavigator = () => {
options={NotificationPrefView.navigationOptions}
/>
+
{
options={NotificationPrefView.navigationOptions}
/>
+
diff --git a/app/stacks/MasterDetailStack/types.ts b/app/stacks/MasterDetailStack/types.ts
index 9d69428a0..d5e871362 100644
--- a/app/stacks/MasterDetailStack/types.ts
+++ b/app/stacks/MasterDetailStack/types.ts
@@ -4,6 +4,8 @@ import { NavigatorScreenParams } from '@react-navigation/core';
import { IAttachment } from '../../definitions/IAttachment';
import { IMessage } from '../../definitions/IMessage';
import { ISubscription, SubscriptionType, TSubscriptionModel } from '../../definitions/ISubscription';
+import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
+import { ILivechatTag } from '../../definitions/ILivechatTag';
export type MasterDetailChatsStackParamList = {
RoomView: {
@@ -111,6 +113,12 @@ export type ModalStackParamList = {
ForwardLivechatView: {
rid: string;
};
+ CloseLivechatView: {
+ rid: string;
+ departmentId?: string;
+ departmentInfo?: ILivechatDepartment;
+ tagsList?: ILivechatTag[];
+ };
CannedResponsesListView: {
rid: string;
};
diff --git a/app/stacks/types.ts b/app/stacks/types.ts
index 6265b3aaa..d09d37f0c 100644
--- a/app/stacks/types.ts
+++ b/app/stacks/types.ts
@@ -11,6 +11,8 @@ import { ICannedResponse } from '../definitions/ICannedResponse';
import { TDataSelect } from '../definitions/IDataSelect';
import { ModalStackParamList } from './MasterDetailStack/types';
import { TThreadModel } from '../definitions';
+import { ILivechatDepartment } from '../definitions/ILivechatDepartment';
+import { ILivechatTag } from '../definitions/ILivechatTag';
export type ChatsStackParamList = {
ModalStackNavigator: NavigatorScreenParams;
@@ -114,6 +116,12 @@ export type ChatsStackParamList = {
ForwardLivechatView: {
rid: string;
};
+ CloseLivechatView: {
+ rid: string;
+ departmentId?: string;
+ departmentInfo?: ILivechatDepartment;
+ tagsList?: ILivechatTag[];
+ };
LivechatEditView: {
room: ISubscription;
roomUser: any; // TODO: Change
diff --git a/app/views/CloseLivechatView.tsx b/app/views/CloseLivechatView.tsx
new file mode 100644
index 000000000..5490bb57e
--- /dev/null
+++ b/app/views/CloseLivechatView.tsx
@@ -0,0 +1,122 @@
+import React, { useState, useLayoutEffect } from 'react';
+import { StyleSheet, ScrollView, Text } from 'react-native';
+import { BlockContext } from '@rocket.chat/ui-kit';
+
+import { IBaseScreen } from '../definitions';
+import I18n from '../i18n';
+import { ChatsStackParamList } from '../stacks/types';
+import { useTheme } from '../theme';
+import KeyboardView from '../containers/KeyboardView';
+import SafeAreaView from '../containers/SafeAreaView';
+import { FormTextInput } from '../containers/TextInput';
+import Button from '../containers/Button';
+import { useAppSelector } from '../lib/hooks';
+import sharedStyles from './Styles';
+import scrollPersistTaps from '../lib/methods/helpers/scrollPersistTaps';
+import { MultiSelect } from '../containers/UIKit/MultiSelect';
+import { closeLivechat } from '../lib/methods/helpers/closeLivechat';
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 16
+ },
+ subtitleText: {
+ marginBottom: 10,
+ fontSize: 14,
+ ...sharedStyles.textSemibold
+ },
+ buttonMarginVertical: { marginVertical: 20 }
+});
+
+const CloseLivechatView = ({ navigation, route }: IBaseScreen) => {
+ const rid = route.params?.rid;
+ const departmentInfo = route.params?.departmentInfo;
+ const tagsList = route.params?.tagsList;
+ const requestTags = departmentInfo?.requestTagBeforeClosingChat;
+
+ const [inputValue, setInputValue] = useState('');
+ const [tagParamSelected, setTagParamSelected] = useState([]);
+
+ const { colors } = useTheme();
+
+ const { isMasterDetail, livechatRequestComment } = useAppSelector(state => ({
+ isMasterDetail: state.app.isMasterDetail,
+ livechatRequestComment: state.settings.Livechat_request_comment_when_closing_conversation as boolean
+ }));
+
+ useLayoutEffect(() => {
+ navigation.setOptions({
+ title: I18n.t('Close_Chat')
+ });
+ }, [navigation]);
+
+ const canSubmit = () => {
+ if (!requestTags && !livechatRequestComment) {
+ return true;
+ }
+ if (requestTags && tagParamSelected.length > 0 && !livechatRequestComment) {
+ return true;
+ }
+ if (livechatRequestComment && !!inputValue && !requestTags) {
+ return true;
+ }
+ if (livechatRequestComment && requestTags && tagParamSelected.length > 0 && !!inputValue) {
+ return true;
+ }
+ return false;
+ };
+
+ const submit = () => {
+ closeLivechat({ rid, isMasterDetail, comment: inputValue, tags: tagParamSelected });
+ };
+
+ return (
+
+
+
+ setInputValue(text)}
+ onSubmitEditing={() => {
+ if (canSubmit()) {
+ submit();
+ }
+ }}
+ />
+
+ {requestTags ? (
+ <>
+ {I18n.t('Tags')}
+ ({ text: { text: name }, value: name }))}
+ onChange={({ value }: { value: string[] }) => {
+ setTagParamSelected(value);
+ }}
+ placeholder={{ text: I18n.t('Select_tags') }}
+ value={tagParamSelected}
+ context={BlockContext.FORM}
+ multiselect
+ inputStyle={{ borderColor: colors.separatorColor, borderWidth: 2 }}
+ />
+ >
+ ) : null}
+
+
+
+
+ );
+};
+
+export default CloseLivechatView;
diff --git a/app/views/RoomActionsView/index.tsx b/app/views/RoomActionsView/index.tsx
index 5912df861..7f91b9996 100644
--- a/app/views/RoomActionsView/index.tsx
+++ b/app/views/RoomActionsView/index.tsx
@@ -46,10 +46,11 @@ import {
import { Services } from '../../lib/services';
import { getSubscriptionByRoomId } from '../../lib/database/services/Subscription';
import { IActionSheetProvider, withActionSheet } from '../../containers/ActionSheet';
-import CloseLivechatSheet from '../../ee/omnichannel/containers/CloseLivechatSheet';
import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
import { closeLivechat } from '../../lib/methods/helpers/closeLivechat';
import { videoConfStartAndJoin } from '../../lib/methods/videoConf';
+import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
+import { ILivechatTag } from '../../definitions/ILivechatTag';
interface IOnPressTouch {
(item: { route?: T; params?: ChatsStackParamList[T]; event?: Function }): void;
@@ -376,29 +377,31 @@ class RoomActionsView extends React.Component {
+ closeLivechat = async () => {
const {
- room: { rid }
+ room: { rid, departmentId }
} = this.state;
- const { livechatRequestComment, showActionSheet, hideActionSheet, isMasterDetail } = this.props;
+ const { livechatRequestComment, isMasterDetail, navigation } = this.props;
+ let departmentInfo: ILivechatDepartment | undefined;
+ let tagsList: ILivechatTag[] | undefined;
- if (!livechatRequestComment) {
+ if (departmentId) {
+ const result = await Services.getDepartmentInfo(departmentId);
+ if (result.success) {
+ departmentInfo = result.department as ILivechatDepartment;
+ }
+ }
+
+ if (departmentInfo?.requestTagBeforeClosingChat) {
+ tagsList = await Services.getTagsList();
+ }
+
+ if (!livechatRequestComment && !departmentInfo?.requestTagBeforeClosingChat) {
const comment = I18n.t('Chat_closed_by_agent');
return closeLivechat({ rid, isMasterDetail, comment });
}
- showActionSheet({
- children: (
- {
- hideActionSheet();
- closeLivechat({ rid, isMasterDetail, comment });
- }}
- onCancel={() => hideActionSheet()}
- />
- ),
- headerHeight: 225
- });
+ navigation.navigate('CloseLivechatView', { rid, departmentId, departmentInfo, tagsList });
};
placeOnHoldLivechat = () => {
diff --git a/app/views/RoomView/RightButtons.tsx b/app/views/RoomView/RightButtons.tsx
index 8b34cdeef..6aaabdcc8 100644
--- a/app/views/RoomView/RightButtons.tsx
+++ b/app/views/RoomView/RightButtons.tsx
@@ -5,6 +5,7 @@ import { Observable, Subscription } from 'rxjs';
import { Dispatch } from 'redux';
import { StackNavigationProp } from '@react-navigation/stack';
+import { ILivechatTag } from '../../definitions/ILivechatTag';
import * as HeaderButton from '../../containers/HeaderButton';
import database from '../../lib/database';
import { getUserSelector } from '../../selectors/login';
@@ -17,7 +18,8 @@ import i18n from '../../i18n';
import { showConfirmationAlert, showErrorAlert } from '../../lib/methods/helpers';
import { onHoldLivechat, returnLivechat } from '../../lib/services/restApi';
import { closeLivechat as closeLivechatService } from '../../lib/methods/helpers/closeLivechat';
-import CloseLivechatSheet from '../../ee/omnichannel/containers/CloseLivechatSheet';
+import { Services } from '../../lib/services';
+import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
interface IRightButtonsProps extends IActionSheetProvider {
userId?: string;
@@ -40,6 +42,7 @@ interface IRightButtonsProps extends IActionSheetProvider {
canPlaceLivechatOnHold: boolean;
};
livechatRequestComment: boolean;
+ departmentId?: string;
}
interface IRigthButtonsState {
@@ -214,35 +217,41 @@ class RightButtonsContainer extends Component {
- const { rid, livechatRequestComment, showActionSheet, hideActionSheet, isMasterDetail } = this.props;
+ closeLivechat = async () => {
+ const { rid, departmentId } = this.props;
+ const { livechatRequestComment, isMasterDetail, navigation } = this.props;
+ let departmentInfo: ILivechatDepartment | undefined;
+ let tagsList: ILivechatTag[] | undefined;
- hideActionSheet();
-
- setTimeout(() => {
- if (!livechatRequestComment) {
- const comment = i18n.t('Chat_closed_by_agent');
- return closeLivechatService({ rid, isMasterDetail, comment });
+ if (departmentId) {
+ const result = await Services.getDepartmentInfo(departmentId);
+ if (result.success) {
+ departmentInfo = result.department as ILivechatDepartment;
}
+ }
- showActionSheet({
- children: (
- {
- hideActionSheet();
- closeLivechatService({ rid, isMasterDetail, comment });
- }}
- onCancel={() => hideActionSheet()}
- />
- ),
- headerHeight: 225
+ if (departmentInfo?.requestTagBeforeClosingChat) {
+ tagsList = await Services.getTagsList();
+ }
+
+ if (!livechatRequestComment && !departmentInfo?.requestTagBeforeClosingChat) {
+ const comment = i18n.t('Chat_closed_by_agent');
+ return closeLivechatService({ rid, isMasterDetail, comment });
+ }
+
+ if (isMasterDetail) {
+ navigation.navigate('ModalStackNavigator', {
+ screen: 'CloseLivechatView',
+ params: { rid, departmentId, departmentInfo, tagsList }
});
- }, 300);
+ } else {
+ navigation.navigate('CloseLivechatView', { rid, departmentId, departmentInfo, tagsList });
+ }
};
showMoreActions = () => {
logEvent(events.ROOM_SHOW_MORE_ACTIONS);
- const { showActionSheet, rid, navigation, omnichannelPermissions } = this.props;
+ const { showActionSheet, rid, navigation, omnichannelPermissions, isMasterDetail } = this.props;
const options = [] as TActionSheetOptionsItem[];
if (omnichannelPermissions.canPlaceLivechatOnHold) {
@@ -257,7 +266,16 @@ class RightButtonsContainer extends Component navigation.navigate('ForwardLivechatView', { rid })
+ onPress: () => {
+ if (isMasterDetail) {
+ navigation.navigate('ModalStackNavigator', {
+ screen: 'ForwardLivechatView',
+ params: { rid }
+ });
+ } else {
+ navigation.navigate('ForwardLivechatView', { rid });
+ }
+ }
});
}
diff --git a/app/views/RoomView/index.tsx b/app/views/RoomView/index.tsx
index f66a09c3b..0c79ddd41 100644
--- a/app/views/RoomView/index.tsx
+++ b/app/views/RoomView/index.tsx
@@ -559,6 +559,7 @@ class RoomView extends React.Component {
let avatar: string | undefined;
let visitor: IVisitor | undefined;
let sourceType: IOmnichannelSource | undefined;
+ let departmentId: string | undefined;
if ('id' in room) {
subtitle = room.topic;
t = room.t;
@@ -568,6 +569,7 @@ class RoomView extends React.Component {
({ id: userId, token } = user);
avatar = room.name;
visitor = room.visitor;
+ departmentId = room.departmentId;
}
if ('source' in room) {
@@ -632,6 +634,7 @@ class RoomView extends React.Component {
encrypted={encrypted}
navigation={navigation}
toggleFollowThread={this.toggleFollowThread}
+ departmentId={departmentId}
/>
)
});