From 63e447caa78c7c02e3f06114fd5bae68f5997ccc Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Mon, 8 Dec 2025 17:40:15 -0300 Subject: [PATCH 01/15] chore: remove feature --- .../server/constant/permissions.ts | 4 - .../currentChats/CurrentChatsPage.tsx | 381 ------------------ .../currentChats/CurrentChatsRoute.tsx | 32 -- .../currentChats/CustomFieldsList.tsx | 75 ---- .../omnichannel/currentChats/FilterByText.tsx | 171 -------- .../views/omnichannel/currentChats/Label.tsx | 8 - .../currentChats/RemoveAllClosed.tsx | 53 --- .../currentChats/RemoveChatButton.tsx | 48 --- .../currentChats/hooks/useCurrentChats.ts | 21 - .../hooks/useRemoveCurrentChatMutation.ts | 23 -- 10 files changed, 816 deletions(-) delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/FilterByText.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/Label.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/RemoveAllClosed.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts delete mode 100644 apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts diff --git a/apps/meteor/app/authorization/server/constant/permissions.ts b/apps/meteor/app/authorization/server/constant/permissions.ts index 4cdc1c05d5b00..600bf15793cc9 100644 --- a/apps/meteor/app/authorization/server/constant/permissions.ts +++ b/apps/meteor/app/authorization/server/constant/permissions.ts @@ -156,10 +156,6 @@ export const permissions = [ _id: 'add-livechat-department-agents', roles: ['livechat-manager', 'livechat-monitor', 'admin'], }, - { - _id: 'view-livechat-current-chats', - roles: ['livechat-manager', 'livechat-monitor', 'admin'], - }, { _id: 'view-livechat-real-time-monitoring', roles: ['livechat-manager', 'livechat-monitor', 'admin'], diff --git a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx deleted file mode 100644 index 1252b05cb2e3f..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx +++ /dev/null @@ -1,381 +0,0 @@ -import type { IOmnichannelRoomWithDepartment } from '@rocket.chat/core-typings'; -import { Callout, Pagination } from '@rocket.chat/fuselage'; -import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; -import type { GETLivechatRoomsParams } from '@rocket.chat/rest-typings'; -import { - GenericTable, - GenericTableBody, - GenericTableCell, - GenericTableHeader, - GenericTableHeaderCell, - GenericTableLoadingTable, - GenericTableRow, - usePagination, - useSort, - Page, - PageHeader, - PageContent, -} from '@rocket.chat/ui-client'; -import { usePermission, useRouter } from '@rocket.chat/ui-contexts'; -import { hashKey } from '@tanstack/react-query'; -import moment from 'moment'; -import type { ComponentProps, ReactElement } from 'react'; -import { memo, useCallback, useMemo, useState } from 'react'; -import { Trans, useTranslation } from 'react-i18next'; - -import CustomFieldsList from './CustomFieldsList'; -import FilterByText from './FilterByText'; -import RemoveChatButton from './RemoveChatButton'; -import { useCurrentChats } from './hooks/useCurrentChats'; -import GenericNoResults from '../../../components/GenericNoResults'; -import { links } from '../../../lib/links'; -import RoomActivityIcon from '../components/RoomActivityIcon'; -import { useCustomFieldsQuery } from '../hooks/useCustomFieldsQuery'; -import { useIsOverMacLimit } from '../hooks/useIsOverMacLimit'; -import { useOmnichannelPriorities } from '../hooks/useOmnichannelPriorities'; -import { PriorityIcon } from '../priorities/PriorityIcon'; - -type DebouncedParams = { - fname: string; - guest: string; - servedBy: string; - department: string; - status: string; - from: string; - to: string; - tags: any[]; -}; - -type CurrentChatQuery = { - agents?: string[]; - offset?: number; - roomName?: string; - departmentId?: string; - open?: boolean; - createdAt?: string; - closedAt?: string; - tags?: string[]; - onhold?: boolean; - customFields?: string; - sort: string; - count?: number; - queued?: boolean; -}; - -type useQueryType = ( - debouncedParams: DebouncedParams, - customFields: { [key: string]: string } | undefined, - [column, direction]: [string, 'asc' | 'desc'], - current: number, - itemsPerPage: 25 | 50 | 100, -) => GETLivechatRoomsParams; - -const sortDir = (sortDir: 'asc' | 'desc'): 1 | -1 => (sortDir === 'asc' ? 1 : -1); - -const currentChatQuery: useQueryType = ( - { guest, servedBy, department, status, from, to, tags }, - customFields, - [column, direction], - current, - itemsPerPage, -) => { - const query: CurrentChatQuery = { - ...(guest && { roomName: guest }), - sort: JSON.stringify({ - [column]: sortDir(direction), - ts: column === 'ts' ? sortDir(direction) : undefined, - }), - ...(itemsPerPage && { count: itemsPerPage }), - ...(current && { offset: current }), - }; - - if (from || to) { - query.createdAt = JSON.stringify({ - ...(from && { - start: moment(new Date(from)).set({ hour: 0, minutes: 0, seconds: 0 }).toISOString(), - }), - ...(to && { - end: moment(new Date(to)).set({ hour: 23, minutes: 59, seconds: 59 }).toISOString(), - }), - }); - } - - if (status !== 'all') { - query.open = status === 'opened' || status === 'onhold' || status === 'queued'; - query.onhold = status === 'onhold'; - query.queued = status === 'queued'; - } - if (servedBy && servedBy !== 'all') { - query.agents = [servedBy]; - } - if (department && department !== 'all') { - query.departmentId = department; - } - - if (tags && tags.length > 0) { - query.tags = tags; - } - - if (customFields && Object.keys(customFields).length > 0) { - const customFieldsQuery = Object.fromEntries(Object.entries(customFields).filter((item) => item[1] !== undefined && item[1] !== '')); - if (Object.keys(customFieldsQuery).length > 0) { - query.customFields = JSON.stringify(customFieldsQuery); - } - } - - return query; -}; - -const CurrentChatsPage = ({ id, onRowClick }: { id?: string; onRowClick: (_id: string) => void }): ReactElement => { - const isWorkspaceOverMacLimit = useIsOverMacLimit(); - const { sortBy, sortDirection, setSort } = useSort<'fname' | 'departmentId' | 'servedBy' | 'priorityWeight' | 'ts' | 'lm' | 'open'>( - 'ts', - 'desc', - ); - const [customFields, setCustomFields] = useState<{ [key: string]: string }>(); - - const { t } = useTranslation(); - const directoryPath = useRouter().buildRoutePath('/omnichannel-directory'); - - const canRemoveClosedChats = usePermission('remove-closed-livechat-room'); - const { enabled: isPriorityEnabled } = useOmnichannelPriorities(); - - const { data: allCustomFields } = useCustomFieldsQuery(); - - const { current, itemsPerPage, setItemsPerPage, setCurrent, ...paginationProps } = usePagination(); - - const [params, setParams] = useState({ - guest: '', - fname: '', - servedBy: '', - status: 'all', - department: '', - from: '', - to: '', - tags: [] as string[], - }); - - const hasCustomFields = useMemo( - () => !!allCustomFields?.customFields?.find((customField) => customField.scope === 'room'), - [allCustomFields], - ); - - const query = useMemo( - () => currentChatQuery(params, customFields, [sortBy, sortDirection], current, itemsPerPage), - [customFields, itemsPerPage, params, sortBy, sortDirection, current], - ); - - const { data, isLoading, isSuccess } = useCurrentChats(query); - - const [defaultQuery] = useState(hashKey([query])); - const queryHasChanged = defaultQuery !== hashKey([query]); - - const onFilter = useEffectEvent((params: DebouncedParams): void => { - setParams(params); - setCurrent(0); - }); - - const renderRow = useCallback( - (room: IOmnichannelRoomWithDepartment) => { - const { _id, fname, servedBy, ts, lm, department, open = false, onHold = false, priorityWeight } = room; - const getStatusText = (open: boolean, onHold: boolean, servedBy: boolean): string => { - if (!open) return t('Closed'); - if (open && !servedBy) return t('Queued'); - return onHold ? t('On_Hold_Chats') : t('Room_Status_Open'); - }; - - return ( - onRowClick(_id)} action data-qa-id={fname}> - {isPriorityEnabled && ( - - - - )} - - {fname} - - - {department ? department.name : ''} - - {servedBy?.username} - - {moment(ts).format('L LTS')} - - - {moment(lm).format('L LTS')} - - - {getStatusText(open, onHold, !!servedBy?.username)} - - {canRemoveClosedChats && ( - - {!open && } - - )} - - ); - }, - [canRemoveClosedChats, onRowClick, isPriorityEnabled, t], - ); - - const headers = ( - <> - {isPriorityEnabled && ( - - {t('Priority')} - - )} - - {t('Name')} - - - {t('Department')} - - - {t('Served_By')} - - - {t('Started_At')} - - - {t('Last_Message')} - - - {t('Status')} - - {canRemoveClosedChats && ( - - {t('Remove')} - - )} - - ); - - // TODO: Missing error state - return ( - - - - - - - Manage conversations in the - contact center. - - - {((isSuccess && data?.rooms.length > 0) || queryHasChanged) && ( - ['setFilter']} - setCustomFields={setCustomFields} - customFields={customFields} - hasCustomFields={hasCustomFields} - /> - )} - {isWorkspaceOverMacLimit && ( - - {t('Talk_to_your_workspace_admin_to_address_this_issue')} - - )} - {isSuccess && data?.rooms.length === 0 && queryHasChanged && } - {isSuccess && data?.rooms.length === 0 && !queryHasChanged && ( - - )} - {isLoading && ( - - {headers} - - - - - )} - {isSuccess && data?.rooms?.length > 0 && ( - <> - - {headers} - - {data.rooms.map((room) => renderRow({ ...room }))} - - - - - )} - - - {id === 'custom-fields' && hasCustomFields && ( - - )} - - ); -}; - -export default memo(CurrentChatsPage); diff --git a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx deleted file mode 100644 index 730cecf1e4008..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; -import { usePermission, useRouteParameter, useRouter } from '@rocket.chat/ui-contexts'; -import { memo } from 'react'; -import type { ReactElement } from 'react'; - -import CurrentChatsPage from './CurrentChatsPage'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import Chat from '../directory/chats/Chat'; - -const CurrentChatsRoute = (): ReactElement => { - const id = useRouteParameter('id'); - - const canViewCurrentChats = usePermission('view-livechat-current-chats'); - const router = useRouter(); - - const onRowClick = useEffectEvent((_id: string) => { - router.navigate(`/omnichannel/current/${_id}`); - }); - - if (!canViewCurrentChats) { - return ; - } - - if (id && id !== 'custom-fields') { - return ; - } - - // TODO: Missing error state - return ; -}; - -export default memo(CurrentChatsRoute); diff --git a/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx b/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx deleted file mode 100644 index e83e08cf32685..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/CustomFieldsList.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import type { ILivechatCustomField } from '@rocket.chat/core-typings'; -import { Field, FieldLabel, FieldRow, TextInput, Select } from '@rocket.chat/fuselage'; -import { - ContextualbarScrollableContent, - ContextualbarHeader, - ContextualbarClose, - ContextualbarDialog, - ContextualbarTitle, -} from '@rocket.chat/ui-client'; -import { useTranslation, useRoute } from '@rocket.chat/ui-contexts'; -import type { ReactElement, Dispatch, SetStateAction } from 'react'; -import { useEffect } from 'react'; -import { Controller, useForm } from 'react-hook-form'; - -type CustomFieldsListProps = { - setCustomFields: Dispatch>; - allCustomFields: ILivechatCustomField[]; -}; - -const CustomFieldsList = ({ setCustomFields, allCustomFields }: CustomFieldsListProps): ReactElement => { - const { register, watch, control } = useForm({ mode: 'onChange' }); - - // TODO: When we refactor the other CurrentChat's fields to use react-hook-form, we need to change this to use the form controller - - useEffect(() => { - const subscription = watch((value) => setCustomFields(value)); - return (): void => subscription.unsubscribe(); - }, [setCustomFields, watch]); - - const t = useTranslation(); - const currentChatsRoute = useRoute('omnichannel-current-chats'); - - return ( - - - {t('Filter_by_Custom_Fields')} - currentChatsRoute.push({ context: '' })} /> - - - {/* TODO: REMOVE FILTER ONCE THE ENDPOINT SUPPORTS A SCOPE PARAMETER */} - {allCustomFields - .filter((customField) => customField.scope !== 'visitor') - .map((customField: ILivechatCustomField) => { - if (customField.type === 'select') { - return ( - - {customField.label} - - ( - - - - - - - - - - - - - - - - - - - - {CurrentChatTags && ( - - - - - - - )} - - ); -}; - -export default FilterByText; diff --git a/apps/meteor/client/views/omnichannel/currentChats/Label.tsx b/apps/meteor/client/views/omnichannel/currentChats/Label.tsx deleted file mode 100644 index e0a06278a5e90..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/Label.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Box } from '@rocket.chat/fuselage'; -import type { ComponentProps } from 'react'; - -type LabelProps = ComponentProps; - -const Label = (props: LabelProps) => ; - -export default Label; diff --git a/apps/meteor/client/views/omnichannel/currentChats/RemoveAllClosed.tsx b/apps/meteor/client/views/omnichannel/currentChats/RemoveAllClosed.tsx deleted file mode 100644 index 74d8d85d1b5ea..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/RemoveAllClosed.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Box, Icon, Menu } from '@rocket.chat/fuselage'; -import { usePermission, useTranslation, useRoute } from '@rocket.chat/ui-contexts'; - -type RemoveAllClosedProps = { - handleClearFilters: any; - handleRemoveClosed: any; - hasCustomFields: boolean; -}; - -const RemoveAllClosed = ({ handleClearFilters, handleRemoveClosed, hasCustomFields, ...props }: RemoveAllClosedProps) => { - const t = useTranslation(); - const directoryRoute = useRoute('omnichannel-current-chats'); - const canRemove = usePermission('remove-closed-livechat-rooms'); - const canViewCustomFields = usePermission('view-livechat-room-customfields'); - - const menuOptions = { - clearFilters: { - label: ( - - - {t('Clear_filters')} - - ), - action: handleClearFilters, - }, - ...(canRemove && { - removeClosed: { - label: ( - - - {t('Delete_all_closed_chats')} - - ), - action: handleRemoveClosed, - }, - }), - ...(canViewCustomFields && - hasCustomFields && { - customFields: { - label: ( - - - {t('Custom_Fields')} - - ), - action: (): void => directoryRoute.push({ context: 'custom-fields' }), - }, - }), - }; - return ; -}; - -export default RemoveAllClosed; diff --git a/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx b/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx deleted file mode 100644 index 2b355f667f13b..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { IconButton } from '@rocket.chat/fuselage'; -import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; -import { GenericModal } from '@rocket.chat/ui-client'; -import { useSetModal, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; -import type { MouseEvent } from 'react'; -import { useTranslation } from 'react-i18next'; - -import { useRemoveCurrentChatMutation } from './hooks/useRemoveCurrentChatMutation'; - -type RemoveChatButtonProps = { _id: string }; - -const RemoveChatButton = ({ _id }: RemoveChatButtonProps) => { - const removeCurrentChatMutation = useRemoveCurrentChatMutation(); - const setModal = useSetModal(); - const dispatchToastMessage = useToastMessageDispatch(); - const { t } = useTranslation(); - - const handleRemoveClick = useEffectEvent(async () => { - removeCurrentChatMutation.mutate(_id); - }); - - const handleDelete = useEffectEvent((e: MouseEvent) => { - e.stopPropagation(); - const onDeleteAgent = async (): Promise => { - try { - await handleRemoveClick(); - dispatchToastMessage({ type: 'success', message: t('Chat_removed') }); - } catch (error) { - dispatchToastMessage({ type: 'error', message: error }); - } - setModal(null); - }; - - setModal( - setModal(null)} - confirmText={t('Delete')} - />, - ); - }); - - return ; -}; - -export default RemoveChatButton; diff --git a/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts b/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts deleted file mode 100644 index cee4e5d7979e6..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import type { GETLivechatRoomsParams, OperationResult } from '@rocket.chat/rest-typings'; -import { useEndpoint } from '@rocket.chat/ui-contexts'; -import type { UseQueryResult } from '@tanstack/react-query'; -import { useQuery } from '@tanstack/react-query'; - -export const useCurrentChats = (query: GETLivechatRoomsParams): UseQueryResult> => { - const currentChats = useEndpoint('GET', '/v1/livechat/rooms'); - - const debouncedQuery = useDebouncedValue(query, 500); - - return useQuery({ - queryKey: ['current-chats', debouncedQuery], - queryFn: () => currentChats(debouncedQuery), - - // TODO: Update this to use an stream of room changes instead of polling - refetchOnWindowFocus: false, - - gcTime: 0, - }); -}; diff --git a/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts b/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts deleted file mode 100644 index d609505017a07..0000000000000 --- a/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { IRoom } from '@rocket.chat/core-typings'; -import { useEndpoint } from '@rocket.chat/ui-contexts'; -import type { UseMutationOptions, UseMutationResult } from '@tanstack/react-query'; -import { useQueryClient, useMutation } from '@tanstack/react-query'; - -export const useRemoveCurrentChatMutation = ( - options?: Omit, 'mutationFn'>, -): UseMutationResult => { - const removeRoom = useEndpoint('POST', '/v1/livechat/rooms.delete'); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: (rid) => removeRoom({ roomId: rid }), - ...options, - - onSuccess: (...args) => { - queryClient.invalidateQueries({ - queryKey: ['current-chats'], - }); - options?.onSuccess?.(...args); - }, - }); -}; From a121d1ea8399a50b61041589a510581ed1f03dbc Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Tue, 9 Dec 2025 12:27:51 -0300 Subject: [PATCH 02/15] chore: normalize routes --- .../hooks/useAdministrationMenu.tsx | 2 +- .../actions/hooks/useAdministrationItems.tsx | 2 +- .../directory/ChatsContextualBar.tsx | 4 +- .../directory/ContactContextualBar.tsx | 11 ++--- .../directory/OmnichannelDirectoryPage.tsx | 32 +++++-------- .../directory/chats/ChatsTable/ChatsTable.tsx | 2 +- .../chats/ChatsTable/ChatsTableFilter.tsx | 7 +-- .../chats/ChatsTable/ChatsTableRow.tsx | 15 +++--- .../chats/ChatsTable/RemoveChatButton.tsx | 48 +++++++++++++++++++ .../chats/ChatsTable/hooks/useCurrentChats.ts | 21 ++++++++ .../hooks/useRemoveCurrentChatMutation.ts | 23 +++++++++ .../directory/contacts/ContactItemMenu.tsx | 14 +++--- .../directory/contacts/ContactTable.tsx | 6 +-- .../directory/contacts/ContactTableRow.tsx | 19 ++++---- .../hooks/useOmnichannelDirectoryRouter.ts | 36 ++++++++++++++ .../hooks/useOmnichannelCloseRoute.ts | 11 +++-- .../meteor/client/views/omnichannel/routes.ts | 6 +-- .../room/HeaderV2/Omnichannel/BackButton.tsx | 12 ++++- .../Omnichannel/OmnichannelRoomHeader.tsx | 10 ++-- 19 files changed, 206 insertions(+), 75 deletions(-) create mode 100644 apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/RemoveChatButton.tsx create mode 100644 apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/hooks/useCurrentChats.ts create mode 100644 apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/hooks/useRemoveCurrentChatMutation.ts create mode 100644 apps/meteor/client/views/omnichannel/directory/hooks/useOmnichannelDirectoryRouter.ts diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.tsx index 7d4190bd00b8e..a269df44206bd 100644 --- a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.tsx +++ b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.tsx @@ -45,7 +45,7 @@ export const useAdministrationMenu = () => { const omnichannel: GenericMenuItemProps = { id: 'omnichannel', content: t('Omnichannel'), - onClick: () => router.navigate('/omnichannel/current'), + onClick: () => router.navigate('/omnichannel'), }; return { diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx index da258f2dc5510..90c14c6be04c4 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx @@ -43,7 +43,7 @@ export const useAdministrationItems = (): GenericMenuItemProps[] => { id: 'omnichannel', content: t('Omnichannel'), icon: 'headset', - onClick: () => router.navigate('/omnichannel/current'), + onClick: () => router.navigate('/omnichannel'), }; const workspaceItem: GenericMenuItemProps = { diff --git a/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx b/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx index 13e81913753a1..6a26d4773d4ee 100644 --- a/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx +++ b/apps/meteor/client/views/omnichannel/directory/ChatsContextualBar.tsx @@ -1,15 +1,17 @@ import { useRouteParameter, useRouter } from '@rocket.chat/ui-contexts'; import ChatsFiltersContextualBar from './chats/ChatsFiltersContextualBar'; +import { useOmnichannelDirectoryRouter } from './hooks/useOmnichannelDirectoryRouter'; import ContactHistoryMessagesList from '../contactHistory/MessageList/ContactHistoryMessagesList'; const ChatsContextualBar = () => { const router = useRouter(); + const directoryRouter = useOmnichannelDirectoryRouter(); const context = useRouteParameter('context'); const id = useRouteParameter('id'); const handleOpenRoom = () => id && router.navigate(`/live/${id}`); - const handleClose = () => router.navigate('/omnichannel-directory/chats'); + const handleClose = () => directoryRouter.navigate({ tab: 'chats' }); if (context === 'filters') { return ; diff --git a/apps/meteor/client/views/omnichannel/directory/ContactContextualBar.tsx b/apps/meteor/client/views/omnichannel/directory/ContactContextualBar.tsx index f73c19a57d138..96bab6344f045 100644 --- a/apps/meteor/client/views/omnichannel/directory/ContactContextualBar.tsx +++ b/apps/meteor/client/views/omnichannel/directory/ContactContextualBar.tsx @@ -1,20 +1,19 @@ -import { useRoute, useRouteParameter } from '@rocket.chat/ui-contexts'; +import { useRouteParameter } from '@rocket.chat/ui-contexts'; import ContactInfo from '../contactInfo/ContactInfo'; import ContactInfoError from '../contactInfo/ContactInfoError'; import EditContactInfo from '../contactInfo/EditContactInfo'; import EditContactInfoWithData from '../contactInfo/EditContactInfoWithData'; +import { useOmnichannelDirectoryRouter } from './hooks/useOmnichannelDirectoryRouter'; const ContactContextualBar = () => { - const directoryRoute = useRoute('omnichannel-directory'); const contactId = useRouteParameter('id'); const context = useRouteParameter('context'); + const omnichannelDirectoryRouter = useOmnichannelDirectoryRouter(); - const handleClose = () => { - directoryRoute.push({ tab: 'contacts' }); - }; + const handleClose = () => omnichannelDirectoryRouter.navigate({ tab: 'contacts' }); - const handleCancel = () => contactId && directoryRoute.push({ tab: 'contacts', context: 'details', id: contactId }); + const handleCancel = () => contactId && omnichannelDirectoryRouter.navigate({ tab: 'contacts', context: 'details', id: contactId }); if (context === 'edit' && contactId) { return ; diff --git a/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx b/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx index 1aef1bf3ec4b9..b02d082140631 100644 --- a/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx +++ b/apps/meteor/client/views/omnichannel/directory/OmnichannelDirectoryPage.tsx @@ -1,38 +1,32 @@ import { Tabs } from '@rocket.chat/fuselage'; import { Page, PageHeader, PageContent } from '@rocket.chat/ui-client'; -import { useRouteParameter, useRouter } from '@rocket.chat/ui-contexts'; +import { useRouteParameter } from '@rocket.chat/ui-contexts'; import { useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import ContextualBarRouter from './ContextualBarRouter'; import ChatsTab from './chats/ChatsTab'; import ContactTab from './contacts/ContactTab'; +import { useOmnichannelDirectoryRouter } from './hooks/useOmnichannelDirectoryRouter'; import ChatsProvider from './providers/ChatsProvider'; -const DEFAULT_TAB = 'chats'; - const OmnichannelDirectoryPage = () => { const { t } = useTranslation(); - const router = useRouter(); const tab = useRouteParameter('tab'); const context = useRouteParameter('context'); - useEffect( - () => - router.subscribeToRouteChange(() => { - if (router.getRouteName() !== 'omnichannel-directory' || !!router.getRouteParameters().tab) { - return; - } - - router.navigate({ - name: 'omnichannel-directory', - params: { tab: DEFAULT_TAB }, - }); - }), - [router], - ); + const router = useOmnichannelDirectoryRouter(); + const routeName = router.getRouteName(); + + useEffect(() => { + if (!routeName || (routeName && !!tab)) { + return; + } + + router.navigate({ tab: 'chats' }); + }, [routeName, router, tab]); - const handleTabClick = useCallback((tab: string) => router.navigate({ name: 'omnichannel-directory', params: { tab } }), [router]); + const handleTabClick = useCallback((tab: string) => router.navigate({ tab }), [router]); return ( diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx index e95cccbf2e0d6..2831adbfad650 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx @@ -15,10 +15,10 @@ import { useTranslation } from 'react-i18next'; import ChatFilterByText from './ChatsTableFilter'; import ChatsTableRow from './ChatsTableRow'; +import { useCurrentChats } from './hooks/useCurrentChats'; import { useChatsQuery } from './useChatsQuery'; import GenericNoResults from '../../../../../components/GenericNoResults/GenericNoResults'; import { links } from '../../../../../lib/links'; -import { useCurrentChats } from '../../../currentChats/hooks/useCurrentChats'; import { useOmnichannelPriorities } from '../../../hooks/useOmnichannelPriorities'; import { useChatsContext } from '../../contexts/ChatsContext'; diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx index a19b1858d8818..731b6d690756d 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx @@ -1,18 +1,19 @@ import { Box, Button, Chip } from '@rocket.chat/fuselage'; import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; import { GenericMenu, GenericModal } from '@rocket.chat/ui-client'; -import { useEndpoint, useRoute, useSetModal, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useEndpoint, useSetModal, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import FilterByText from '../../../../../components/FilterByText'; import { useChatsContext } from '../../contexts/ChatsContext'; +import { useOmnichannelDirectoryRouter } from '../../hooks/useOmnichannelDirectoryRouter'; const ChatsTableFilter = () => { const { t } = useTranslation(); const setModal = useSetModal(); const dispatchToastMessage = useToastMessageDispatch(); - const directoryRoute = useRoute('omnichannel-directory'); + const omnichannelDirectoryRouter = useOmnichannelDirectoryRouter(); const queryClient = useQueryClient(); const removeClosedRooms = useEndpoint('POST', '/v1/livechat/rooms.removeAllClosedRooms'); @@ -65,7 +66,7 @@ const ChatsTableFilter = () => { >