diff --git a/apps/meteor/client/hooks/roomActions/useRoomInfoRoomAction.ts b/apps/meteor/client/hooks/roomActions/useRoomInfoRoomAction.ts
index 1b7608ff5212..573211b6fbd8 100644
--- a/apps/meteor/client/hooks/roomActions/useRoomInfoRoomAction.ts
+++ b/apps/meteor/client/hooks/roomActions/useRoomInfoRoomAction.ts
@@ -2,7 +2,7 @@ import { lazy, useMemo } from 'react';
import type { RoomToolboxActionConfig } from '../../views/room/contexts/RoomToolboxContext';
-const ChatsContextualBar = lazy(() => import('../../views/omnichannel/directory/chats/contextualBar/ChatsContextualBar'));
+const ChatsContextualBar = lazy(() => import('../../views/omnichannel/directory/chats/ChatInfo/ChatInfoRouter'));
export const useRoomInfoRoomAction = () => {
return useMemo(
diff --git a/apps/meteor/client/views/omnichannel/contactHistory/ContactHistory.tsx b/apps/meteor/client/views/omnichannel/contactHistory/ContactHistory.tsx
index 955c1918be05..5375132c455f 100644
--- a/apps/meteor/client/views/omnichannel/contactHistory/ContactHistory.tsx
+++ b/apps/meteor/client/views/omnichannel/contactHistory/ContactHistory.tsx
@@ -11,7 +11,7 @@ const ContactHistory = () => {
return (
<>
{chatId && chatId !== '' ? (
-
+
) : (
)}
diff --git a/apps/meteor/client/views/omnichannel/contactHistory/MessageList/ContactHistoryMessagesList.tsx b/apps/meteor/client/views/omnichannel/contactHistory/MessageList/ContactHistoryMessagesList.tsx
index 3bf6385a19a0..70e2619be58e 100644
--- a/apps/meteor/client/views/omnichannel/contactHistory/MessageList/ContactHistoryMessagesList.tsx
+++ b/apps/meteor/client/views/omnichannel/contactHistory/MessageList/ContactHistoryMessagesList.tsx
@@ -1,12 +1,24 @@
-import { Box, Icon, Margins, States, StatesIcon, StatesSubtitle, StatesTitle, TextInput, Throbber } from '@rocket.chat/fuselage';
+import {
+ Box,
+ Button,
+ ButtonGroup,
+ ContextualbarFooter,
+ Icon,
+ Margins,
+ States,
+ StatesIcon,
+ StatesSubtitle,
+ StatesTitle,
+ TextInput,
+ Throbber,
+} from '@rocket.chat/fuselage';
import { useSetting, useTranslation, useUserPreference } from '@rocket.chat/ui-contexts';
-import type { ChangeEvent, Dispatch, ReactElement, SetStateAction } from 'react';
+import type { ChangeEvent, ReactElement } from 'react';
import React, { useMemo, useState } from 'react';
import { Virtuoso } from 'react-virtuoso';
import {
ContextualbarHeader,
- ContextualbarAction,
ContextualbarIcon,
ContextualbarTitle,
ContextualbarClose,
@@ -21,18 +33,17 @@ import { isMessageSequential } from '../../../room/MessageList/lib/isMessageSequ
import ContactHistoryMessage from './ContactHistoryMessage';
import { useHistoryMessageList } from './useHistoryMessageList';
-const ContactHistoryMessagesList = ({
- chatId,
- setChatId,
- close,
-}: {
+type ContactHistoryMessagesListProps = {
chatId: string;
- setChatId: Dispatch>;
- close: () => void;
-}): ReactElement => {
- const [text, setText] = useState('');
+ onClose: () => void;
+ onOpenRoom?: () => void;
+};
+
+const ContactHistoryMessagesList = ({ chatId, onClose, onOpenRoom }: ContactHistoryMessagesListProps) => {
const t = useTranslation();
+ const [text, setText] = useState('');
const showUserAvatar = !!useUserPreference('displayAvatars');
+
const { itemsList: messageList, loadMoreItems } = useHistoryMessageList(
useMemo(() => ({ roomId: chatId, filter: text }), [chatId, text]),
);
@@ -47,10 +58,9 @@ const ContactHistoryMessagesList = ({
return (
<>
- setChatId('')} title={t('Back')} name='arrow-back' />
{t('Chat_History')}
-
+
@@ -111,6 +121,13 @@ const ContactHistoryMessagesList = ({
)}
+ {onOpenRoom && (
+
+
+
+
+
+ )}
>
);
};
diff --git a/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx b/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx
index b7bad83f87e1..7493a72becb2 100644
--- a/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx
+++ b/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx
@@ -1,75 +1,21 @@
-import { Box } from '@rocket.chat/fuselage';
-import { useRoute, useRouteParameter, useTranslation } from '@rocket.chat/ui-contexts';
+import { useRouteParameter, useRouter } from '@rocket.chat/ui-contexts';
import React from 'react';
-import {
- Contextualbar,
- ContextualbarHeader,
- ContextualbarIcon,
- ContextualbarTitle,
- ContextualbarAction,
- ContextualbarClose,
-} from '../../../components/Contextualbar';
-import Chat from './chats/Chat';
-import ChatInfoDirectory from './chats/contextualBar/ChatInfoDirectory';
-import { RoomEditWithData } from './chats/contextualBar/RoomEdit';
-import { FormSkeleton } from './components';
-import { useOmnichannelRoomInfo } from './hooks/useOmnichannelRoomInfo';
-
-const ChatsContextualBar = ({ chatReload }: { chatReload?: () => void }) => {
- const t = useTranslation();
-
- const directoryRoute = useRoute('omnichannel-directory');
+import ContactHistoryMessagesList from '../contactHistory/MessageList/ContactHistoryMessagesList';
+const ChatsContextualBar = () => {
+ const router = useRouter();
const context = useRouteParameter('context');
- const id = useRouteParameter('id') || '';
-
- const openInRoom = () => id && directoryRoute.push({ tab: 'chats', id, context: 'view' });
-
- const handleClose = () => directoryRoute.push({ tab: 'chats' });
-
- const handleCancel = () => id && directoryRoute.push({ tab: 'chats', id, context: 'info' });
+ const id = useRouteParameter('id');
- const { data: room, isLoading, isError, refetch: reloadInfo } = useOmnichannelRoomInfo(id);
-
- if (context === 'view' && id) {
- return ;
- }
-
- if (isLoading) {
- return (
-
-
-
- );
- }
+ const handleOpenRoom = () => id && router.navigate(`/live/${id}`);
+ const handleClose = () => router.navigate('/omnichannel-directory/chats');
- if (isError || !room) {
- return {t('Room_not_found')};
+ if (context === 'info' && id) {
+ return ;
}
- return (
-
-
- {context === 'info' && (
- <>
-
- {t('Room_Info')}
-
- >
- )}
- {context === 'edit' && (
- <>
-
- {t('edit-room')}
- >
- )}
-
-
- {context === 'info' && }
- {context === 'edit' && id && }
-
- );
+ return null;
};
export default ChatsContextualBar;
diff --git a/apps/meteor/client/views/omnichannel/directory/ContextualBarRouter.tsx b/apps/meteor/client/views/omnichannel/directory/ContextualBarRouter.tsx
index 6ffd6383c9df..0ab0cdb59162 100644
--- a/apps/meteor/client/views/omnichannel/directory/ContextualBarRouter.tsx
+++ b/apps/meteor/client/views/omnichannel/directory/ContextualBarRouter.tsx
@@ -5,14 +5,14 @@ import CallsContextualBarDirectory from './CallsContextualBarDirectory';
import ChatsContextualBar from './ChatsContextualBar';
import ContactContextualBar from './ContactContextualBar';
-const ContextualBarRouter = ({ chatReload }: { chatReload?: () => void }) => {
+const ContextualBarRouter = () => {
const tab = useRouteParameter('tab');
switch (tab) {
case 'contacts':
return ;
case 'chats':
- return ;
+ return ;
case 'calls':
return ;
default:
diff --git a/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx b/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx
index dff1cd467b02..34d52bbfb399 100644
--- a/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx
+++ b/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx
@@ -4,7 +4,6 @@ import React, { useEffect, useCallback } from 'react';
import { ContextualbarDialog } from '../../../components/Contextualbar';
import { Page, PageHeader, PageContent } from '../../../components/Page';
-import { queryClient } from '../../../lib/queryClient';
import ContextualBarRouter from './ContextualBarRouter';
import CallTab from './calls/CallTab';
import ChatTab from './chats/ChatTab';
@@ -35,8 +34,6 @@ const OmnichannelDirectoryPage = () => {
const handleTabClick = useCallback((tab) => router.navigate({ name: 'omnichannel-directory', params: { tab } }), [router]);
- const chatReload = () => queryClient.invalidateQueries({ queryKey: ['current-chats'] });
-
return (
@@ -46,7 +43,7 @@ const OmnichannelDirectoryPage = () => {
{t('Contacts')}
handleTabClick('chats')}>
- {t('Chats' as any /* TODO: this is going to change to Conversations */)}
+ {t('Chats')}
handleTabClick('calls')}>
{t('Calls')}
@@ -60,7 +57,7 @@ const OmnichannelDirectoryPage = () => {
{context && (
-
+
)}
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatInfo.js b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/ChatInfo.js
similarity index 100%
rename from apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatInfo.js
rename to apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/ChatInfo.js
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatsContextualBar.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/ChatInfoRouter.tsx
similarity index 91%
rename from apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatsContextualBar.tsx
rename to apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/ChatInfoRouter.tsx
index d78f7e9a4ab9..28d938de8271 100644
--- a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatsContextualBar.tsx
+++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/ChatInfoRouter.tsx
@@ -5,7 +5,7 @@ import { ContextualbarHeader, ContextualbarIcon, ContextualbarTitle, Contextualb
import { useRoom } from '../../../../room/contexts/RoomContext';
import { useRoomToolbox } from '../../../../room/contexts/RoomToolboxContext';
import ChatInfo from './ChatInfo';
-import { RoomEditWithData } from './RoomEdit';
+import RoomEdit from './RoomEdit';
const PATH = 'live';
@@ -36,7 +36,7 @@ const ChatsContextualBar = () => {
{context === 'edit' ? (
-
+
) : (
)}
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/DepartmentField.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/DepartmentField.tsx
similarity index 100%
rename from apps/meteor/client/views/omnichannel/directory/chats/contextualBar/DepartmentField.tsx
rename to apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/DepartmentField.tsx
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEdit.tsx
similarity index 100%
rename from apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx
rename to apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEdit.tsx
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEditWithData.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEditWithData.tsx
similarity index 100%
rename from apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEditWithData.tsx
rename to apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEditWithData.tsx
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/index.ts b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/index.ts
new file mode 100644
index 000000000000..99205f80da8b
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/index.ts
@@ -0,0 +1 @@
+export { default } from './RoomEditWithData';
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/VisitorClientInfo.js b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/VisitorClientInfo.js
similarity index 100%
rename from apps/meteor/client/views/omnichannel/directory/chats/contextualBar/VisitorClientInfo.js
rename to apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/VisitorClientInfo.js
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatInfoDirectory.js b/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatInfoDirectory.js
deleted file mode 100644
index ed7b5fdafb86..000000000000
--- a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/ChatInfoDirectory.js
+++ /dev/null
@@ -1,178 +0,0 @@
-import { Box, Margins, Tag, Button, ButtonGroup } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useToastMessageDispatch, useRoute, useUserSubscription, useTranslation } from '@rocket.chat/ui-contexts';
-import { Meteor } from 'meteor/meteor';
-import moment from 'moment';
-import React, { useEffect, useMemo, useState } from 'react';
-
-import { hasPermission } from '../../../../../../app/authorization/client';
-import { ContextualbarScrollableContent, ContextualbarFooter } from '../../../../../components/Contextualbar';
-import { InfoPanelField, InfoPanelLabel, InfoPanelText } from '../../../../../components/InfoPanel';
-import MarkdownText from '../../../../../components/MarkdownText';
-import { useEndpointData } from '../../../../../hooks/useEndpointData';
-import { useFormatDateAndTime } from '../../../../../hooks/useFormatDateAndTime';
-import { useFormatDuration } from '../../../../../hooks/useFormatDuration';
-import CustomField from '../../../components/CustomField';
-import { AgentField, ContactField, SlaField } from '../../components';
-import PriorityField from '../../components/PriorityField';
-import { formatQueuedAt } from '../../utils/formatQueuedAt';
-import DepartmentField from './DepartmentField';
-import VisitorClientInfo from './VisitorClientInfo';
-
-function ChatInfoDirectory({ id, route = undefined, room }) {
- const t = useTranslation();
-
- const formatDateAndTime = useFormatDateAndTime();
- const { value: allCustomFields, phase: stateCustomFields } = useEndpointData('/v1/livechat/custom-fields');
- const [customFields, setCustomFields] = useState([]);
- const formatDuration = useFormatDuration();
-
- const {
- ts,
- tags,
- closedAt,
- departmentId,
- v,
- servedBy,
- metrics,
- topic,
- waitingResponse,
- responseBy,
- slaId,
- priorityId,
- livechatData,
- queuedAt,
- } = room || { room: { v: {} } };
-
- const routePath = useRoute(route || 'omnichannel-directory');
- const canViewCustomFields = () => hasPermission('view-livechat-room-customfields');
- const subscription = useUserSubscription(id);
- const hasGlobalEditRoomPermission = hasPermission('save-others-livechat-room-info');
- const hasLocalEditRoomPermission = servedBy?._id === Meteor.userId();
- const visitorId = v?._id;
- const queueStartedAt = queuedAt || ts;
-
- const queueTime = useMemo(() => formatQueuedAt(room), [room]);
-
- const dispatchToastMessage = useToastMessageDispatch();
- useEffect(() => {
- if (allCustomFields) {
- const { customFields: customFieldsAPI } = allCustomFields;
- setCustomFields(customFieldsAPI);
- }
- }, [allCustomFields, stateCustomFields]);
-
- const checkIsVisibleAndScopeRoom = (key) => {
- const field = customFields.find(({ _id }) => _id === key);
- if (field && field.visibility === 'visible' && field.scope === 'room') {
- return true;
- }
- return false;
- };
-
- const onEditClick = useMutableCallback(() => {
- const hasEditAccess = !!subscription || hasLocalEditRoomPermission || hasGlobalEditRoomPermission;
- if (!hasEditAccess) {
- return dispatchToastMessage({ type: 'error', message: t('Not_authorized') });
- }
-
- routePath.push({
- tab: route ? 'room-info' : 'chats',
- context: 'edit',
- id,
- });
- });
-
- return (
- <>
-
-
- {room && v && }
- {visitorId && }
- {servedBy && }
- {departmentId && }
- {tags && tags.length > 0 && (
-
- {t('Tags')}
-
- {tags.map((tag) => (
-
-
- {tag}
-
-
- ))}
-
-
- )}
- {topic && (
-
- {t('Topic')}
-
-
-
-
- )}
- {queueStartedAt && (
-
- {t('Queue_Time')}
- {queueTime}
-
- )}
- {closedAt && (
-
- {t('Chat_Duration')}
- {moment(closedAt).from(moment(ts), true)}
-
- )}
- {ts && (
-
- {t('Created_at')}
- {formatDateAndTime(ts)}
-
- )}
- {closedAt && (
-
- {t('Closed_At')}
- {formatDateAndTime(closedAt)}
-
- )}
- {servedBy?.ts && (
-
- {t('Taken_at')}
- {formatDateAndTime(servedBy.ts)}
-
- )}
- {metrics?.response?.avg && formatDuration(metrics.response.avg) && (
-
- {t('Avg_response_time')}
- {formatDuration(metrics.response.avg)}
-
- )}
- {!waitingResponse && responseBy?.lastMessageTs && (
-
- {t('Inactivity_Time')}
- {moment(responseBy.lastMessageTs).fromNow(true)}
-
- )}
- {canViewCustomFields() &&
- livechatData &&
- Object.keys(livechatData).map(
- (key) => checkIsVisibleAndScopeRoom(key) && livechatData[key] && ,
- )}
- {slaId && }
- {priorityId && }
-
-
-
-
-
-
-
- >
- );
-}
-
-export default ChatInfoDirectory;
diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/index.ts b/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/index.ts
deleted file mode 100644
index dcfd1c14d2d9..000000000000
--- a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as RoomEditWithData } from './RoomEditWithData';
diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts
index 323d41550592..b1f64b17b94c 100644
--- a/apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts
+++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts
@@ -79,7 +79,7 @@ test.describe('omnichannel- export chat transcript as PDF', () => {
await agent.poHomeChannel.transcript.contactCenterSearch.type(newUser.name);
await page.waitForTimeout(3000);
await agent.poHomeChannel.transcript.firstRow.click();
- await agent.poHomeChannel.transcript.viewFullConversation.click();
+ await agent.poHomeChannel.transcript.btnOpenChat.click();
await agent.poHomeChannel.content.btnSendTranscript.click();
await expect(agent.poHomeChannel.content.btnSendTranscriptAsPDF).toHaveAttribute('aria-disabled', 'false');
await agent.poHomeChannel.content.btnSendTranscriptAsPDF.click();
diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel-transcript.ts b/apps/meteor/tests/e2e/page-objects/omnichannel-transcript.ts
index d0249933d438..d7ece60a5ef6 100644
--- a/apps/meteor/tests/e2e/page-objects/omnichannel-transcript.ts
+++ b/apps/meteor/tests/e2e/page-objects/omnichannel-transcript.ts
@@ -36,8 +36,8 @@ export class OmnichannelTranscript {
return this.page.locator('//tr[1]//td[1]');
}
- get viewFullConversation(): Locator {
- return this.page.locator('//button[@title="View full conversation"]/i');
+ get btnOpenChat(): Locator {
+ return this.page.getByRole('dialog').getByRole('button', { name: 'Open chat', exact: true });
}
get DownloadedPDF(): Locator {
diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json
index 91b1dab69ee9..142691224076 100644
--- a/packages/i18n/src/locales/en.i18n.json
+++ b/packages/i18n/src/locales/en.i18n.json
@@ -1006,6 +1006,7 @@
"Chatops_Enabled": "Enable Chatops",
"Chatops_Title": "Chatops Panel",
"Chatops_Username": "Chatops Username",
+ "Chats": "Chats",
"Chat_Duration": "Chat Duration",
"Chats_removed": "Chats Removed",
"Check_All": "Check All",
@@ -4040,6 +4041,7 @@
"Open_call": "Open call",
"Open_call_in_new_tab": "Open call in new tab",
"Open_channel_user_search": "`%s` - Open Channel / User search",
+ "Open_chat": "Open chat",
"Open_conversations": "Open Conversations",
"Open_Days": "Open days",
"Open_days_of_the_week": "Open Days of the Week",