diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarItemSort.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarItemSort.tsx new file mode 100644 index 0000000000000..430718e036820 --- /dev/null +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarItemSort.tsx @@ -0,0 +1,18 @@ +import { SidebarV2Action } from '@rocket.chat/fuselage'; +import { GenericMenu } from '@rocket.chat/ui-client'; +import type { HTMLAttributes } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { useSortMenu } from './hooks/useSortMenu'; + +type NavBarItemSortProps = Omit, 'is'>; + +const NavBarItemSort = (props: NavBarItemSortProps) => { + const { t } = useTranslation(); + + const sections = useSortMenu(); + + return ; +}; + +export default NavBarItemSort; diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarPagesGroup.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarPagesGroup.tsx index f258706d513be..946ea592502be 100644 --- a/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarPagesGroup.tsx +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/NavBarPagesGroup.tsx @@ -6,6 +6,7 @@ import NavBarItemCreateNew from './NavBarItemCreateNew'; import NavBarItemDirectoryPage from './NavBarItemDirectoryPage'; import NavBarItemHomePage from './NavBarItemHomePage'; import NavBarItemMarketPlaceMenu from './NavBarItemMarketPlaceMenu'; +import NavBarItemSort from './NavBarItemSort'; import NavBarPagesStackMenu from './NavBarPagesStackMenu'; const NavBarPagesGroup = () => { @@ -26,6 +27,7 @@ const NavBarPagesGroup = () => { )} {showMarketplace && !isMobile && } + {!isMobile && } ); diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useGroupingListItems.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useGroupingListItems.tsx new file mode 100644 index 0000000000000..67c56f2a51535 --- /dev/null +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useGroupingListItems.tsx @@ -0,0 +1,35 @@ +import { CheckBox } from '@rocket.chat/fuselage'; +import type { GenericMenuItemProps } from '@rocket.chat/ui-client'; +import { useEndpoint, useUserPreference } from '@rocket.chat/ui-contexts'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +export const useGroupingListItems = (): GenericMenuItemProps[] => { + const { t } = useTranslation(); + + const sidebarGroupByType = useUserPreference('sidebarGroupByType'); + const sidebarShowUnread = useUserPreference('sidebarShowUnread'); + + const saveUserPreferences = useEndpoint('POST', '/v1/users.setPreferences'); + + const useHandleChange = (key: 'sidebarGroupByType' | 'sidebarShowUnread', value: boolean): (() => void) => + useCallback(() => saveUserPreferences({ data: { [key]: value } }), [key, value]); + + const handleChangeGroupByType = useHandleChange('sidebarGroupByType', !sidebarGroupByType); + const handleChangeShowUnread = useHandleChange('sidebarShowUnread', !sidebarShowUnread); + + return [ + { + id: 'unread', + content: t('Unread'), + icon: 'flag', + addon: , + }, + { + id: 'types', + content: t('Types'), + icon: 'group-by-type', + addon: , + }, + ]; +}; diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useGrouppingListItems.spec.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useGrouppingListItems.spec.tsx new file mode 100644 index 0000000000000..490c41042a8d0 --- /dev/null +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useGrouppingListItems.spec.tsx @@ -0,0 +1,19 @@ +import { renderHook } from '@testing-library/react'; + +import { useGroupingListItems } from './useGroupingListItems'; + +it('should render groupingList items', async () => { + const { result } = renderHook(() => useGroupingListItems()); + + expect(result.current[0]).toEqual( + expect.objectContaining({ + id: 'unread', + }), + ); + + expect(result.current[1]).toEqual( + expect.objectContaining({ + id: 'types', + }), + ); +}); diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortMenu.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortMenu.tsx new file mode 100644 index 0000000000000..8364d8e146e60 --- /dev/null +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortMenu.tsx @@ -0,0 +1,18 @@ +import { useTranslation } from 'react-i18next'; + +import { useGroupingListItems } from './useGroupingListItems'; +import { useSortModeItems } from './useSortModeItems'; + +export const useSortMenu = () => { + const { t } = useTranslation(); + + const sortModeItems = useSortModeItems(); + const groupingListItems = useGroupingListItems(); + + const sections = [ + { title: t('Sort_By'), items: sortModeItems }, + { title: t('Group_by'), items: groupingListItems }, + ]; + + return sections; +}; diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortModeItems.spec.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortModeItems.spec.tsx new file mode 100644 index 0000000000000..fbda604809f0a --- /dev/null +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortModeItems.spec.tsx @@ -0,0 +1,19 @@ +import { renderHook } from '@testing-library/react'; + +import { useSortModeItems } from './useSortModeItems'; + +it('should render sortMode items', async () => { + const { result } = renderHook(() => useSortModeItems()); + + expect(result.current[0]).toEqual( + expect.objectContaining({ + id: 'activity', + }), + ); + + expect(result.current[1]).toEqual( + expect.objectContaining({ + id: 'name', + }), + ); +}); diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortModeItems.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortModeItems.tsx new file mode 100644 index 0000000000000..c1dfb4f3d71ec --- /dev/null +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/hooks/useSortModeItems.tsx @@ -0,0 +1,41 @@ +import { RadioButton } from '@rocket.chat/fuselage'; +import type { GenericMenuItemProps } from '@rocket.chat/ui-client'; +import { useEndpoint, useUserPreference } from '@rocket.chat/ui-contexts'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { + OmnichannelSortingDisclaimer, + useOmnichannelSortingDisclaimer, +} from '../../../components/Omnichannel/OmnichannelSortingDisclaimer'; + +export const useSortModeItems = (): GenericMenuItemProps[] => { + const { t } = useTranslation(); + + const saveUserPreferences = useEndpoint('POST', '/v1/users.setPreferences'); + const sidebarSortBy = useUserPreference<'activity' | 'alphabetical'>('sidebarSortby', 'activity'); + const isOmnichannelEnabled = useOmnichannelSortingDisclaimer(); + + const useHandleChange = (value: 'alphabetical' | 'activity'): (() => void) => + useCallback(() => saveUserPreferences({ data: { sidebarSortby: value } }), [value]); + + const setToAlphabetical = useHandleChange('alphabetical'); + const setToActivity = useHandleChange('activity'); + + return [ + { + id: 'activity', + content: t('Activity'), + icon: 'clock', + addon: , + description: sidebarSortBy === 'activity' && isOmnichannelEnabled && , + }, + { + id: 'name', + content: t('Name'), + icon: 'sort-az', + addon: , + description: sidebarSortBy === 'alphabetical' && isOmnichannelEnabled && , + }, + ]; +}; diff --git a/apps/meteor/client/components/GenericNoResults/GenericNoResults.tsx b/apps/meteor/client/components/GenericNoResults/GenericNoResults.tsx index ee0d8ea040996..420137bcb46d0 100644 --- a/apps/meteor/client/components/GenericNoResults/GenericNoResults.tsx +++ b/apps/meteor/client/components/GenericNoResults/GenericNoResults.tsx @@ -9,7 +9,6 @@ type GenericNoResultsProps = { icon?: IconName | null; title?: string; description?: string; - buttonPrimary?: boolean; } & LinkProps & ButtonProps; @@ -19,7 +18,6 @@ const GenericNoResults = ({ description, buttonTitle, buttonAction, - buttonPrimary = true, linkHref, linkText, }: GenericNoResultsProps) => { @@ -33,9 +31,7 @@ const GenericNoResults = ({ {description && {description}} {buttonTitle && buttonAction && ( - - {buttonTitle} - + {buttonTitle} )} {linkText && linkHref && ( diff --git a/apps/meteor/client/sidebarv2/RoomList/SidebarItem.tsx b/apps/meteor/client/sidebarv2/RoomList/SidebarItem.tsx index 73806479eb43c..42b06edcb22b2 100644 --- a/apps/meteor/client/sidebarv2/RoomList/SidebarItem.tsx +++ b/apps/meteor/client/sidebarv2/RoomList/SidebarItem.tsx @@ -26,7 +26,7 @@ const SidebarItem = ({ icon, title, actions, unread, menu, badges, room, ...prop const handlePointerEnter = () => setMenuVisibility(true); return ( - + diff --git a/apps/meteor/client/sidebarv2/RoomList/SidebarItemWithData.tsx b/apps/meteor/client/sidebarv2/RoomList/SidebarItemWithData.tsx index 30585cce22f40..763543cd3a491 100644 --- a/apps/meteor/client/sidebarv2/RoomList/SidebarItemWithData.tsx +++ b/apps/meteor/client/sidebarv2/RoomList/SidebarItemWithData.tsx @@ -29,6 +29,8 @@ type RoomListRowProps = { const SidebarItemWithData = ({ room, id, style, t, videoConfActions }: RoomListRowProps) => { const title = roomCoordinator.getRoomName(room.t, room) || ''; + const href = roomCoordinator.getRouteLink(room.t, room) || ''; + const { unreadTitle, unreadVariant, showUnread, unreadCount, highlightUnread: highlighted } = useUnreadDisplay(room); const icon = ( @@ -85,10 +87,7 @@ const SidebarItemWithData = ({ room, id, style, t, videoConfActions }: RoomListR switchSidePanelTab('channels', { parentRid: room.rid }); }, [room, switchSidePanelTab]); - const buttonProps = useButtonPattern((e) => { - e.preventDefault(); - handleClick(); - }); + const buttonProps = useButtonPattern(handleClick); return ( { return ( - {isDiscussionEnabled && } diff --git a/apps/meteor/client/views/navigation/contexts/RoomsNavigationContext.ts b/apps/meteor/client/views/navigation/contexts/RoomsNavigationContext.ts index 0ff54f161942a..51fddaf6806c7 100644 --- a/apps/meteor/client/views/navigation/contexts/RoomsNavigationContext.ts +++ b/apps/meteor/client/views/navigation/contexts/RoomsNavigationContext.ts @@ -1,4 +1,4 @@ -import type { ILivechatInquiryRecord, IRoom } from '@rocket.chat/core-typings'; +import type { ISubscription, ILivechatInquiryRecord, IRoom } from '@rocket.chat/core-typings'; import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; import type { Keys as IconName } from '@rocket.chat/icons'; import type { SubscriptionWithRoom, TranslationKey } from '@rocket.chat/ui-contexts'; @@ -48,15 +48,23 @@ export const sidePanelFiltersConfig: { [Key in AllGroupsKeys]: { title: Translat title: 'Direct_Messages', icon: 'at', }, + unread: { + title: 'Unread', + icon: 'flag', + }, + conversations: { + title: 'Conversations', + icon: 'chat', + }, }; export type SidePanelFiltersKeys = 'all' | 'mentions' | 'favorites' | 'discussions' | 'inProgress' | 'queue' | 'onHold'; -export const collapsibleFilters: SideBarFiltersKeys[] = ['teams', 'channels', 'directMessages']; +export const collapsibleFilters: SideBarFiltersKeys[] = ['unread', 'conversations', 'teams', 'channels', 'directMessages']; export type SidePanelFiltersUnreadKeys = `${SidePanelFiltersKeys}_unread`; export type SidePanelFilters = SidePanelFiltersKeys | SidePanelFiltersUnreadKeys; -export type SideBarFiltersKeys = 'teams' | 'channels' | 'directMessages'; +export type SideBarFiltersKeys = 'teams' | 'channels' | 'directMessages' | 'conversations' | 'unread'; export type SideBarFiltersUnreadKeys = `${SideBarFiltersKeys}_unread`; export type SideBarFilters = SidePanelFiltersKeys | SidePanelFiltersUnreadKeys; @@ -156,16 +164,49 @@ export const useSideBarRoomsList = (): { }; }; +export const isUnreadSubscription = (subscription: Partial) => { + if (subscription.hideUnreadStatus) { + return false; + } + + return Boolean( + subscription.userMentions || + subscription.groupMentions || + subscription.tunread?.length || + subscription.tunreadUser?.length || + subscription.unread || + subscription.alert, + ); +}; + export const useSidePanelRoomsListTab = (tab: AllGroupsKeys) => { const [, unread] = useSidePanelFilter(); - const roomSet = useRoomsListContext().groups.get(getFilterKey(tab, unread)); + const roomSet = useRoomsListContext().groups.get(tab); + const roomsList = useMemo(() => { if (!roomSet) { return []; } - return Array.from(roomSet); - }, [roomSet]); + if (!unread) { + return Array.from(roomSet); + } + + return Array.from(roomSet) + .reduce( + (result, room) => { + if (isUnreadSubscription(room)) { + result[0].push(room); + return result; + } + + result[1].push(room); + return result; + }, + [[], []] as [Array, Array], + ) + .flat(); + }, [roomSet, unread]); return roomsList; }; diff --git a/apps/meteor/client/views/navigation/hooks/useSortQueryOptions.spec.ts b/apps/meteor/client/views/navigation/hooks/useSortQueryOptions.spec.ts new file mode 100644 index 0000000000000..26128508f2216 --- /dev/null +++ b/apps/meteor/client/views/navigation/hooks/useSortQueryOptions.spec.ts @@ -0,0 +1,25 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { renderHook } from '@testing-library/react'; + +import { useSortQueryOptions } from './useSortQueryOptions'; + +it("should return query option to sort by last message when user preference is 'activity'", () => { + const { result } = renderHook(() => useSortQueryOptions(), { + wrapper: mockAppRoot().withUserPreference('sidebarSortby', 'activity').build(), + }); + expect(result.current.sort).toHaveProperty('lm', -1); +}); + +it("should return query option to sort by name when user preference is 'name'", () => { + const { result } = renderHook(() => useSortQueryOptions(), { + wrapper: mockAppRoot().withUserPreference('sidebarSortby', 'name').build(), + }); + expect(result.current.sort).toHaveProperty('lowerCaseName', 1); +}); + +it("should return query option to sort by fname when user preference is 'name' and showRealName is true", () => { + const { result } = renderHook(() => useSortQueryOptions(), { + wrapper: mockAppRoot().withUserPreference('sidebarSortby', 'name').withSetting('UI_Use_Real_Name', true).build(), + }); + expect(result.current.sort).toHaveProperty('lowerCaseFName', 1); +}); diff --git a/apps/meteor/client/views/navigation/hooks/useSortQueryOptions.ts b/apps/meteor/client/views/navigation/hooks/useSortQueryOptions.ts new file mode 100644 index 0000000000000..e65c6f9411f92 --- /dev/null +++ b/apps/meteor/client/views/navigation/hooks/useSortQueryOptions.ts @@ -0,0 +1,32 @@ +import { useUserPreference, useSetting } from '@rocket.chat/ui-contexts'; +import { useMemo } from 'react'; + +export const useSortQueryOptions = (): { + sort: + | { + lm?: -1 | 1 | undefined; + } + | { + lowerCaseFName: -1 | 1; + lm?: -1 | 1 | undefined; + } + | { + lowerCaseName: -1 | 1; + lm?: -1 | 1 | undefined; + }; +} => { + const sortBy = useUserPreference('sidebarSortby'); + const showRealName = useSetting('UI_Use_Real_Name'); + + return useMemo( + () => ({ + sort: { + ...(sortBy === 'activity' && { lm: -1 }), + ...(sortBy !== 'activity' && { + ...(showRealName ? { lowerCaseFName: 1 } : { lowerCaseName: 1 }), + }), + }, + }), + [sortBy, showRealName], + ); +}; diff --git a/apps/meteor/client/views/navigation/providers/RoomsNavigationProvider.tsx b/apps/meteor/client/views/navigation/providers/RoomsNavigationProvider.tsx index 9a5c53b8a0f13..657ff04daacdb 100644 --- a/apps/meteor/client/views/navigation/providers/RoomsNavigationProvider.tsx +++ b/apps/meteor/client/views/navigation/providers/RoomsNavigationProvider.tsx @@ -17,12 +17,12 @@ import { useMemo } from 'react'; import { useOmnichannelEnabled } from '../../../hooks/omnichannel/useOmnichannelEnabled'; import { useQueuedInquiries } from '../../../hooks/omnichannel/useQueuedInquiries'; import type { GroupedUnreadInfoData, AllGroupsKeys, AllGroupsKeysWithUnread } from '../contexts/RoomsNavigationContext'; -import { RoomsNavigationContext, getEmptyUnreadInfo } from '../contexts/RoomsNavigationContext'; +import { RoomsNavigationContext, getEmptyUnreadInfo, isUnreadSubscription } from '../contexts/RoomsNavigationContext'; import { useSidePanelFilters } from '../hooks/useSidePanelFilters'; import { useSidePanelParentRid } from '../hooks/useSidePanelParentRid'; +import { useSortQueryOptions } from '../hooks/useSortQueryOptions'; const query = { open: { $ne: false } }; -const sortOptions = { sort: { lm: -1 } } as const; const emptyQueue: ILivechatInquiryRecord[] = []; @@ -53,9 +53,6 @@ const updateGroupUnreadInfo = ( }; }; -const isUnread = (room: SubscriptionWithRoom | ILivechatInquiryRecord) => - 'alert' in room && (room.alert || room.unread || room.tunread?.length) && !room.hideUnreadStatus; - const hasMention = (room: SubscriptionWithRoom) => room.userMentions || room.groupMentions || room.tunreadUser?.length || room.tunreadGroup?.length; @@ -65,9 +62,12 @@ type UnreadGroupDataMap = Map; const useRoomsGroups = (): [GroupMap, UnreadGroupDataMap] => { const showOmnichannel = useOmnichannelEnabled(); const favoritesEnabled = useUserPreference('sidebarShowFavorites'); + const sidebarShowUnread = useUserPreference('sidebarShowUnread'); + const sidebarGroupByType = useUserPreference('sidebarGroupByType'); const isDiscussionEnabled = useSetting('Discussion_enabled'); + const options = useSortQueryOptions(); - const rooms = useUserSubscriptions(query, sortOptions); + const rooms = useUserSubscriptions(query, options); const inquiries = useQueuedInquiries(); const queue = inquiries.enabled ? inquiries.queue : emptyQueue; @@ -90,8 +90,8 @@ const useRoomsGroups = (): [GroupMap, UnreadGroupDataMap] => { getGroupSet(key).add(room); - if (isUnread(room)) { - getGroupSet(`${key}_unread`).add(room); + if (isUnreadSubscription(room)) { + // getGroupSet(`${key}_unread`).add(room); const currentUnreadData = unreadGroupData.get(key) || getEmptyUnreadInfo(); const unreadInfo = updateGroupUnreadInfo(room, currentUnreadData); @@ -104,6 +104,16 @@ const useRoomsGroups = (): [GroupMap, UnreadGroupDataMap] => { return; } + if (isOmnichannelRoom(room) && showOmnichannel) { + if (room.onHold) { + return setGroupRoom('onHold', room); + } + + return setGroupRoom('inProgress', room); + } + + setGroupRoom('all', room); + if (hasMention(room)) { setGroupRoom('mentions', room); } @@ -112,35 +122,36 @@ const useRoomsGroups = (): [GroupMap, UnreadGroupDataMap] => { setGroupRoom('favorites', room); } - if (isTeamRoom(room)) { - setGroupRoom('teams', room); - } - if (isDiscussionEnabled && isDiscussion(room)) { setGroupRoom('discussions', room); + return; } - if ((isPrivateRoom(room) || isPublicRoom(room)) && !isDiscussion(room) && !isTeamRoom(room)) { - setGroupRoom('channels', room); + if (sidebarShowUnread && isUnreadSubscription(room)) { + setGroupRoom('unread', room); + return; } - if (isOmnichannelRoom(room) && showOmnichannel) { - if (room.onHold) { - return setGroupRoom('onHold', room); - } + if (!sidebarGroupByType) { + setGroupRoom('conversations', room); + return; + } - return setGroupRoom('inProgress', room); + if (isTeamRoom(room)) { + setGroupRoom('teams', room); + } + + if ((isPrivateRoom(room) || isPublicRoom(room)) && !isDiscussion(room) && !isTeamRoom(room)) { + setGroupRoom('channels', room); } if (isDirectMessageRoom(room)) { setGroupRoom('directMessages', room); } - - setGroupRoom('all', room); }); return [groups, unreadGroupData]; - }, [rooms, showOmnichannel, queue, favoritesEnabled, isDiscussionEnabled]), + }, [showOmnichannel, queue, rooms, sidebarShowUnread, sidebarGroupByType, favoritesEnabled, isDiscussionEnabled]), 50, ); }; diff --git a/apps/meteor/client/views/navigation/sidepanel/SidePanel.tsx b/apps/meteor/client/views/navigation/sidepanel/SidePanel.tsx index 11f96a212cdba..1c4c773b3400c 100644 --- a/apps/meteor/client/views/navigation/sidepanel/SidePanel.tsx +++ b/apps/meteor/client/views/navigation/sidepanel/SidePanel.tsx @@ -50,9 +50,7 @@ const SidePanel = ({ title, currentTab, unreadOnly, toggleUnreadOnly, rooms }: S - {rooms && rooms.length === 0 && ( - - )} + {rooms && rooms.length === 0 && } void }; +type SidePanelNoResultsProps = { currentTab: AllGroupsKeys }; -const SidePanelNoResults = ({ currentTab, unreadOnly, toggleUnreadOnly }: SidePanelNoResultsProps) => { +const SidePanelNoResults = ({ currentTab }: SidePanelNoResultsProps) => { const { t } = useTranslation(); - const buttonProps = unreadOnly - ? { - buttonAction: toggleUnreadOnly, - buttonTitle: t('Show_all'), - buttonPrimary: false, - } - : {}; - switch (currentTab) { case 'mentions': return ( - + ); case 'favorites': return ( ); case 'discussions': return ( ); case 'inProgress': return ( ); case 'queue': return ( ); case 'onHold': return ( ); case 'teams': return ( - + ); case 'channels': - return ( - - ); + return ; case 'directMessages': - return ( - - ); + return ; default: - return ( - - ); + return ; } }; diff --git a/apps/meteor/client/views/navigation/sidepanel/SidePanelRouter.tsx b/apps/meteor/client/views/navigation/sidepanel/SidePanelRouter.tsx index 90c2d0c866c2d..929932e2b0410 100644 --- a/apps/meteor/client/views/navigation/sidepanel/SidePanelRouter.tsx +++ b/apps/meteor/client/views/navigation/sidepanel/SidePanelRouter.tsx @@ -5,7 +5,6 @@ import SidePanelQueue from './omnichannel/tabs/SidePanelQueue'; import SidePanelOnHold from './omnichannel/tabs/SidepanelOnHold'; import SidePanelDiscussions from './tabs/SidePanelDiscussions'; import SidePanelFavorites from './tabs/SidePanelFavorites'; -import SidePanelMentions from './tabs/SidePanelMentions'; import SidePanelRooms from './tabs/SidePanelRooms'; const SidePanelRouter = () => { @@ -15,8 +14,6 @@ const SidePanelRouter = () => { switch (currentTab) { case 'all': return ; - case 'mentions': - return ; case 'favorites': return ; case 'discussions': diff --git a/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentRoom/SidePanelParentRoom.tsx b/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentRoom/SidePanelParentRoom.tsx index 55b0bde285aa5..4edcea27884d1 100644 --- a/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentRoom/SidePanelParentRoom.tsx +++ b/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentRoom/SidePanelParentRoom.tsx @@ -1,6 +1,5 @@ import type { ISubscription } from '@rocket.chat/core-typings'; import { isPrivateRoom } from '@rocket.chat/core-typings'; -import { useButtonPattern } from '@rocket.chat/fuselage-hooks'; import { roomCoordinator } from '../../../../../lib/rooms/roomCoordinator'; import SidePanelTag from '../SidePanelTag'; @@ -10,13 +9,8 @@ const SidePanelParentRoom = ({ subscription }: { subscription: ISubscription }) const icon = isPrivateRoom(subscription) ? 'hashtag-lock' : 'hashtag'; const roomName = roomCoordinator.getRoomName(subscription?.t, subscription); - const buttonProps = useButtonPattern((e) => { - e.preventDefault(); - roomCoordinator.openRouteLink(subscription.t, { ...subscription }); - }); - return ( - + {icon && } {roomName} diff --git a/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentTeam.tsx b/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentTeam.tsx index 70d2c94f6738a..eb319ac8b784c 100644 --- a/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentTeam.tsx +++ b/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/SidePanelParentTeam.tsx @@ -1,4 +1,3 @@ -import { useButtonPattern } from '@rocket.chat/fuselage-hooks'; import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; import SidePanelTag from './SidePanelTag'; @@ -6,19 +5,14 @@ import SidePanelTagIcon from './SidePanelTagIcon'; import { useParentTeamData } from './useParentTeamData'; const SidePanelParentTeam = ({ room }: { room: SubscriptionWithRoom }) => { - const { redirectToMainRoom, teamName, shouldDisplayTeam, teamInfoError, isTeamPublic } = useParentTeamData(room.teamId); - - const buttonProps = useButtonPattern((e) => { - e.preventDefault(); - redirectToMainRoom(); - }); + const { teamName, shouldDisplayTeam, teamInfoError, isTeamPublic } = useParentTeamData(room.teamId); if (teamInfoError || !shouldDisplayTeam) { return null; } return ( - + {teamName} diff --git a/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/useParentTeamData.ts b/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/useParentTeamData.ts index 7dddf12ac6d8d..464ff7a5da5a9 100644 --- a/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/useParentTeamData.ts +++ b/apps/meteor/client/views/navigation/sidepanel/SidepanelItem/useParentTeamData.ts @@ -3,7 +3,6 @@ import { TEAM_TYPE } from '@rocket.chat/core-typings'; import { useUserId } from '@rocket.chat/ui-contexts'; import { useTeamInfoQuery } from '../../../../hooks/useTeamInfoQuery'; -import { goToRoomById } from '../../../../lib/utils/goToRoomById'; import { useUserTeamsQuery } from '../../../room/hooks/useUserTeamsQuery'; type APIErrorResult = { success: boolean; error: string }; @@ -31,19 +30,9 @@ export const useParentTeamData = (teamId?: ITeam['_id']) => { const isTeamPublic = teamInfo?.type === TEAM_TYPE.PUBLIC; const shouldDisplayTeam = isTeamPublic || userBelongsToTeam; - const redirectToMainRoom = (): void => { - const rid = teamInfo?.roomId; - if (!rid) { - return; - } - - goToRoomById(rid); - }; - return { teamName: teamInfo?.name, isLoading: userTeamsLoading || teamInfoLoading, - redirectToMainRoom, teamInfoError, shouldDisplayTeam, isTeamPublic, diff --git a/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.spec.ts b/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.spec.ts new file mode 100644 index 0000000000000..d083c2fe31450 --- /dev/null +++ b/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.spec.ts @@ -0,0 +1,126 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; +import { renderHook } from '@testing-library/react'; + +import { createFakeSubscription } from '../../../../../tests/mocks/data'; +import { emptyUnread, createMockGlobalStore } from '../../../../../tests/mocks/utils'; +import { isUnreadSubscription } from '../../contexts/RoomsNavigationContext'; + +const fakeTeam = { ...createFakeSubscription({ alert: true }) }; +const fakeChannel = { ...createFakeSubscription({ t: 'c', alert: true }) }; + +const teamChildChannel = { + ...createFakeSubscription({ t: 'c', ...emptyUnread, prid: fakeTeam.rid }), +}; +const unreadTeamChildChannel = { + ...createFakeSubscription({ t: 'c', alert: true, prid: fakeTeam.rid }), +}; +const childChannel = { + ...createFakeSubscription({ t: 'c', ...emptyUnread, prid: fakeChannel.rid }), +}; +const userMentionsChildChannel = { + ...createFakeSubscription({ t: 'c', userMentions: 1, prid: fakeChannel.rid }), +}; +const groupMentionsChildChannel = { + ...createFakeSubscription({ t: 'c', groupMentions: 1, prid: fakeChannel.rid }), +}; +const unreadChildChannel = { + ...createFakeSubscription({ t: 'c', unread: 1, prid: fakeChannel.rid }), +}; +const tUnreadChildChannel = { + ...createFakeSubscription({ t: 'c', tunread: ['1'], prid: fakeChannel.rid }), +}; +const tUnreadUserChildChannel = { + ...createFakeSubscription({ t: 'c', tunreadUser: ['1'], prid: fakeChannel.rid }), +}; +const tUnreadGroupChildChannel = { + ...createFakeSubscription({ t: 'c', tunreadGroup: ['1'], prid: fakeChannel.rid }), +}; + +const teamsSubscriptions = [fakeTeam, teamChildChannel, unreadTeamChildChannel] as unknown as SubscriptionWithRoom[]; +const channelsSubscriptions = [ + fakeChannel, + childChannel, + userMentionsChildChannel, + groupMentionsChildChannel, + unreadChildChannel, + tUnreadChildChannel, + tUnreadUserChildChannel, + tUnreadGroupChildChannel, +] as unknown as SubscriptionWithRoom[]; + +const subscriptionsMock = [...teamsSubscriptions, ...channelsSubscriptions] as unknown as SubscriptionWithRoom[]; + +jest.mock('../../../../stores/Subscriptions', () => { + return { + Subscriptions: createMockGlobalStore(subscriptionsMock), + }; +}); + +it('should return all subscriptions parent of fakeChannel', async () => { + const { useChannelsChildrenList } = await import('./useChannelsChildrenList'); + + const { result } = renderHook(() => useChannelsChildrenList(fakeChannel.rid, false), { + wrapper: mockAppRoot().withSubscriptions(subscriptionsMock).build(), + }); + + expect(result.current).toHaveLength(channelsSubscriptions.length); + expect(result.current[0].rid).toBe(fakeChannel.rid); + + if (result.current[0].rid === fakeChannel.rid) return; + expect(result.current[0].prid).toBe(fakeChannel.rid); +}); + +it('should return unread subscriptions after parent but before read ones for channels', async () => { + const { useChannelsChildrenList } = await import('./useChannelsChildrenList'); + + const { result } = renderHook(() => useChannelsChildrenList(fakeChannel.rid, true), { + wrapper: mockAppRoot().withSubscriptions(subscriptionsMock).build(), + }); + + expect(result.current).toHaveLength(channelsSubscriptions.length); + expect(result.current[0].rid).toBe(fakeChannel.rid); + + expect(isUnreadSubscription(result.current[1])).toBe(true); + expect(isUnreadSubscription(result.current[2])).toBe(true); + expect(isUnreadSubscription(result.current[3])).toBe(true); + expect(isUnreadSubscription(result.current[4])).toBe(true); + expect(isUnreadSubscription(result.current[5])).toBe(true); + expect(isUnreadSubscription(result.current[6])).toBe(true); + + expect(isUnreadSubscription(result.current[7])).toBe(false); + + if (result.current[0].rid === fakeChannel.rid) return; + expect(result.current[0].prid).toBe(fakeChannel.rid); +}); + +it('should return subscriptions parent of fakeTeam', async () => { + const { useChannelsChildrenList } = await import('./useChannelsChildrenList'); + + const { result } = renderHook(() => useChannelsChildrenList(fakeTeam.rid, false), { + wrapper: mockAppRoot().withSubscriptions(subscriptionsMock).build(), + }); + + expect(result.current).toHaveLength(teamsSubscriptions.length); + expect(result.current[0].rid).toBe(fakeTeam.rid); + + if (result.current[0].rid === fakeTeam.rid) return; + expect(result.current[0].prid).toBe(fakeTeam.rid); +}); + +it('should return unread subscriptions after parent but before read ones for teams', async () => { + const { useChannelsChildrenList } = await import('./useChannelsChildrenList'); + + const { result } = renderHook(() => useChannelsChildrenList(fakeTeam.rid, true), { + wrapper: mockAppRoot().withSubscriptions(subscriptionsMock).build(), + }); + + expect(result.current).toHaveLength(teamsSubscriptions.length); + expect(result.current[0].rid).toBe(fakeTeam.rid); + + expect(isUnreadSubscription(result.current[1])).toBe(true); + expect(isUnreadSubscription(result.current[2])).toBe(false); + + if (result.current[0].rid === fakeTeam.rid) return; + expect(result.current[0].prid).toBe(fakeTeam.rid); +}); diff --git a/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.ts b/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.ts index 3457d1c9bcdff..5345710fb044d 100644 --- a/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.ts +++ b/apps/meteor/client/views/navigation/sidepanel/hooks/useChannelsChildrenList.ts @@ -1,11 +1,9 @@ -import type { ISubscription } from '@rocket.chat/core-typings'; import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; import { useShallow } from 'zustand/shallow'; import { pipe } from '../../../../lib/cachedStores'; import { Subscriptions } from '../../../../stores'; - -const filterUnread = (subscription: ISubscription, unreadOnly: boolean) => !unreadOnly || subscription.unread > 0; +import { isUnreadSubscription } from '../../contexts/RoomsNavigationContext'; const sortByLmPipe = pipe().sortByField('lm', -1); @@ -13,9 +11,31 @@ const sortByLmPipe = pipe().sortByField('lm', -1); * This helper function is used to ensure that the main room (main team room or parent's discussion room) * is always at the top of the list. */ -const getMainRoomAndSort = (records: SubscriptionWithRoom[]) => { - const [mainRoom, ...rest] = records; - return [mainRoom, ...sortByLmPipe.apply(rest)]; +const getMainRoomAndSort = (records: SubscriptionWithRoom[], unreadOnly: boolean) => { + const mainRoom = records.find((record) => record.teamMain || (!record.prid && !record.teamId)); + const filteredRecords = records.filter((record) => mainRoom?.rid !== record.rid); + const sortedRecords = sortByLmPipe.apply(filteredRecords); + const rest = !unreadOnly + ? sortedRecords + : sortedRecords + .reduce( + (result, record) => { + if (isUnreadSubscription(record)) { + result[0].push(record); + return result; + } + result[1].push(record); + return result; + }, + [[] as SubscriptionWithRoom[], [] as SubscriptionWithRoom[]], + ) + .flat(); + + if (mainRoom) { + rest.unshift(mainRoom); + } + + return rest; }; export const useChannelsChildrenList = (parentRid: string, unreadOnly: boolean, teamId?: string) => { @@ -23,19 +43,15 @@ export const useChannelsChildrenList = (parentRid: string, unreadOnly: boolean, useShallow((state) => { const records = state.filter((subscription) => { if (parentRid === subscription.prid || parentRid === subscription.rid) { - return filterUnread(subscription, unreadOnly); + return true; } if (teamId && subscription.teamId === teamId) { - return filterUnread(subscription, unreadOnly); + return true; } return false; }); - if (!records.length) { - return []; - } - - return getMainRoomAndSort(records); + return getMainRoomAndSort(records, unreadOnly); }), ); }; diff --git a/apps/meteor/client/views/navigation/sidepanel/tabs/SidePanelRooms.tsx b/apps/meteor/client/views/navigation/sidepanel/tabs/SidePanelRooms.tsx index 26eeab9c67e7f..be0c1678c72a8 100644 --- a/apps/meteor/client/views/navigation/sidepanel/tabs/SidePanelRooms.tsx +++ b/apps/meteor/client/views/navigation/sidepanel/tabs/SidePanelRooms.tsx @@ -1,5 +1,6 @@ import { useUserSubscription } from '@rocket.chat/ui-contexts'; +import SidePanelAll from './SidePanelAll'; import SidePanelChannels from './SidePanelChannels'; import SidePanelTeams from './SidePanelTeams'; import { withErrorBoundary } from '../../../../components/withErrorBoundary'; @@ -10,7 +11,7 @@ const SidePanelRooms = ({ parentRid }: { parentRid: string }) => { const subscription = useUserSubscription(parentRid); if (!subscription) { - return null; + return ; } switch (currentTab) { @@ -19,8 +20,6 @@ const SidePanelRooms = ({ parentRid }: { parentRid: string }) => { case 'channels': case 'directMessages': return ; - default: - return null; } }; diff --git a/apps/meteor/tests/e2e/feature-preview.spec.ts b/apps/meteor/tests/e2e/feature-preview.spec.ts index 2148d6039ec8b..fe0b669a25317 100644 --- a/apps/meteor/tests/e2e/feature-preview.spec.ts +++ b/apps/meteor/tests/e2e/feature-preview.spec.ts @@ -449,25 +449,6 @@ test.describe.serial('feature preview', () => { await expect(poHomeChannel.sidebar.favoritesTeamCollabFilter).toHaveAttribute('aria-selected', 'true'); }); - test('should open parent team when clicking button on sidepanel discussion item', async ({ page }) => { - await page.goto(`/group/${sidepanelTeam}`); - - const discussionName = faker.string.uuid(); - await poHomeChannel.content.btnMenuMoreActions.click(); - await page.getByRole('menuitem', { name: 'Discussion' }).click(); - await poHomeChannel.content.inputDiscussionName.fill(discussionName); - await poHomeChannel.content.btnCreateDiscussionModal.click(); - - await expect(page.getByRole('heading', { name: discussionName })).toBeVisible(); - - await expect(poHomeChannel.sidepanel.getItemByName(discussionName).getByRole('button', { name: sidepanelTeam })).toBeVisible(); - - await poHomeChannel.sidepanel.getItemByName(discussionName).getByRole('button', { name: sidepanelTeam }).click(); - - await expect(page).toHaveURL(`/group/${sidepanelTeam}`); - await expect(page.getByRole('heading', { name: sidepanelTeam })).toBeVisible(); - }); - test('should show all filters and tablist on sidepanel', async ({ page }) => { await page.goto('/home'); @@ -475,7 +456,6 @@ test.describe.serial('feature preview', () => { await expect(poHomeChannel.sidebar.omnichannelFilters).toBeVisible(); await expect(poHomeChannel.sidebar.allTeamCollabFilter).toBeVisible(); - await expect(poHomeChannel.sidebar.mentionsTeamCollabFilter).toBeVisible(); await expect(poHomeChannel.sidebar.favoritesTeamCollabFilter).toBeVisible(); await expect(poHomeChannel.sidebar.discussionsTeamCollabFilter).toBeVisible(); }); @@ -555,7 +535,6 @@ test.describe.serial('feature preview', () => { await poHomeChannel.sidepanel.unreadToggleLabel.click(); await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).toBeVisible(); await test.step('send a thread message from another user', async () => { await user1Page.goto(`/channel/${targetChannel}`); @@ -565,7 +544,6 @@ test.describe.serial('feature preview', () => { await user1Channel.content.sendMessageInThread('hello thread'); }); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).not.toBeVisible(); await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).toBeVisible(); await expect( poHomeChannel.sidepanel.getItemByName(targetChannel).getByRole('status', { name: '1 unread threaded message' }), @@ -574,15 +552,12 @@ test.describe.serial('feature preview', () => { await poHomeChannel.sidepanel.getItemByName(targetChannel).click(); await poHomeChannel.content.waitForChannel(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).not.toBeVisible(); await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).toBeVisible(); await expect( poHomeChannel.sidepanel.getItemByName(targetChannel).getByRole('status', { name: '1 unread threaded message' }), ).toBeVisible(); await poHomeChannel.content.openReplyInThread(); - - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).toBeVisible(); await user1Page.close(); }); @@ -613,17 +588,10 @@ test.describe.serial('feature preview', () => { await poHomeChannel.sidepanel.unreadToggleLabel.click(); await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).toBeVisible(); - - await poHomeChannel.sidebar.mentionsTeamCollabFilter.click(); - - await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread mentions' })).toBeVisible(); await poHomeChannel.sidebar.favoritesTeamCollabFilter.click(); await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread favorite rooms' })).toBeVisible(); }); await poHomeChannel.navbar.homeButton.click(); @@ -637,19 +605,11 @@ test.describe.serial('feature preview', () => { await test.step('unread mentions badge should be visible on all filters', async () => { await poHomeChannel.sidebar.allTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).not.toBeVisible(); await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).toBeVisible(); await expect(poHomeChannel.sidepanel.getItemByName(targetChannel).getByRole('status', { name: '1 mention' })).toBeVisible(); await expect(poHomeChannel.sidebar.allTeamCollabFilter.getByRole('status', { name: '1 mention from All' })).toBeVisible(); - await poHomeChannel.sidebar.mentionsTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread mentions' })).not.toBeVisible(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).toBeVisible(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel).getByRole('status', { name: '1 mention' })).toBeVisible(); - await expect(poHomeChannel.sidebar.mentionsTeamCollabFilter.getByRole('status', { name: '1 mention from Mentions' })).toBeVisible(); - await poHomeChannel.sidebar.favoritesTeamCollabFilter.click(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread favorite rooms' })).not.toBeVisible(); await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).toBeVisible(); await expect(poHomeChannel.sidepanel.getItemByName(targetChannel).getByRole('status', { name: '1 mention' })).toBeVisible(); await expect( @@ -664,25 +624,14 @@ test.describe.serial('feature preview', () => { await test.step('unread mentions badge should not be visible on any filters', async () => { await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).not.toBeVisible(); - - await poHomeChannel.sidebar.mentionsTeamCollabFilter.click(); - - await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).not.toBeVisible(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread mentions' })).toBeVisible(); await poHomeChannel.sidebar.favoritesTeamCollabFilter.click(); await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).not.toBeVisible(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread favorite rooms' })).toBeVisible(); await poHomeChannel.sidebar.allTeamCollabFilter.click(); await expect(poHomeChannel.sidepanel.unreadCheckbox).toBeChecked(); - await expect(poHomeChannel.sidepanel.getItemByName(targetChannel)).not.toBeVisible(); - await expect(poHomeChannel.sidepanel.sidepanel.getByRole('heading', { name: 'No unread rooms' })).toBeVisible(); }); await user1Page.close(); @@ -744,10 +693,10 @@ test.describe.serial('feature preview', () => { await expect(poHomeChannel.sidebar.sidebar).toBeVisible(); await expect(poHomeChannel.sidepanel.sidepanel).not.toBeVisible(); - await poHomeChannel.sidebar.mentionsTeamCollabFilter.click(); + await poHomeChannel.sidebar.favoritesTeamCollabFilter.click(); await expect(poHomeChannel.sidepanel.sidepanel).toBeVisible(); - await expect(poHomeChannel.sidepanel.getSidepanelHeader('Mentions')).toBeVisible(); + await expect(poHomeChannel.sidepanel.getSidepanelHeader('Favorites')).toBeVisible(); }); test('should close nav region when clicking outside of it', async ({ page }) => { @@ -805,21 +754,19 @@ test.describe.serial('feature preview', () => { }); }); - test('should not open rooms when clicking on sidebar filters', async ({ page }) => { + test('should open rooms when clicking on sidebar filter', async ({ page }) => { await page.goto('/home'); await poHomeChannel.sidenav.waitForHome(); await expect(poHomeChannel.sidebar.channelsList).toBeVisible(); - // TODO: flaky without force click, for some reason opens 2nd channel in list await poHomeChannel.sidebar.getSearchRoomByName(sidepanelTeam).click({ force: true }); await expect(poHomeChannel.sidepanel.sidepanel).toBeVisible(); await expect(poHomeChannel.sidepanel.getSidepanelHeader(sidepanelTeam)).toBeVisible(); await expect(poHomeChannel.sidepanel.getTeamItemByName(sidepanelTeam)).toBeVisible(); - await expect(page).toHaveURL('/home'); - await expect(poHomeChannel.sidenav.homepageHeader).toBeVisible(); + await expect(page).toHaveURL(`/group/${sidepanelTeam}`); }); test('should open room when clicking on sidepanel item', async ({ page }) => { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/sidebar.ts b/apps/meteor/tests/e2e/page-objects/fragments/sidebar.ts index 63760cc4214ec..58b444c855a04 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/sidebar.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/sidebar.ts @@ -24,10 +24,6 @@ export class Sidebar { return this.teamCollabFilters.getByRole('button', { name: 'All' }); } - get mentionsTeamCollabFilter(): Locator { - return this.teamCollabFilters.getByRole('button').filter({ hasText: 'Mentions' }); - } - get favoritesTeamCollabFilter(): Locator { return this.teamCollabFilters.getByRole('button', { name: 'Favorites' }); } diff --git a/apps/meteor/tests/mocks/utils/createMockGlobalStore.ts b/apps/meteor/tests/mocks/utils/createMockGlobalStore.ts new file mode 100644 index 0000000000000..47cefb83ba633 --- /dev/null +++ b/apps/meteor/tests/mocks/utils/createMockGlobalStore.ts @@ -0,0 +1,8 @@ +export function createMockGlobalStore(records: any[]) { + return { + use: (selector: any) => selector(records), + get state() { + return records; + }, + }; +} diff --git a/apps/meteor/tests/mocks/utils/index.ts b/apps/meteor/tests/mocks/utils/index.ts new file mode 100644 index 0000000000000..fc3d3cf04fcca --- /dev/null +++ b/apps/meteor/tests/mocks/utils/index.ts @@ -0,0 +1,11 @@ +export { createMockGlobalStore } from './createMockGlobalStore'; + +export const emptyUnread = { + userMentions: 0, + groupMentions: 0, + unread: 0, + tunread: undefined, + tunreadUser: undefined, + tunreadGroup: undefined, + alert: false, +}; diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index d5b5e2620f6cc..55a8d6d166e8c 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -3594,16 +3594,10 @@ "No_channels_yet_description": "Channels associated to this contact will appear here.", "No_chats_in_progress": "No chats in progress", "No_chats_in_progress_description": "Chats assigned to you will appear here.", - "No_unread_chats_in_progress": "No unread chats in progress", - "No_unread_chats_in_progress_description": "Unread chats assigned to you will appear here.", "No_chats_in_queue": "No chats in queue", "No_chats_in_queue_description": "Queued chats will appear here.", - "No_unread_chats_in_queue": "No unread chats in queue", - "No_unread_chats_in_queue_description": "Unread queued chats will appear here.", "No_chats_on_hold": "No chats on hold", "No_chats_on_hold_description": "Chats on hold will appear here.", - "No_unread_chats_on_hold": "No unread chats on hold", - "No_unread_chats_on_hold_description": "Unread chats on hold will appear here.", "No_chats_yet": "No chats yet", "No_chats_yet_description": "All your chats will appear here.", "No_contacts_yet": "No contacts yet", @@ -3623,19 +3617,11 @@ "No_discussions_description": "Discussions you've joined will appear hear.", "No_discussions_channels_filter_description": "Discussions belonging to this channel will appear hear.", "No_discussions_dms_filter_description": "Discussions belonging to this user will appear hear.", - "No_unread_channels_or_discussions": "No unread channels or discussions", - "No_unread_channels_or_discussions_description": "Unread channels and discussions belonging to this team will appear hear.", - "No_unread_discussions": "No unread discussions", - "No_unread_discussions_description": "Unread discussions you've joined will appear hear.", - "No_unread_discussions_channels_filter_description": "Unread discussions belonging to this channel will appear hear.", - "No_unread_discussions_dms_filter_description": "Unread discussions belonging to this user will appear hear.", "No_discussions_yet": "No discussions yet", "No_emojis_found": "No emojis found", "No_feature_to_preview": "No feature to preview", "No_favorite_rooms": "No favorite rooms", "No_favorite_rooms_description": "Your favorite rooms will appear here.", - "No_unread_favorite_rooms": "No unread favorite rooms", - "No_unread_favorite_rooms_description": "Your unread favorite rooms will appear here.", "No_files_found": "No files found", "No_files_found_to_prune": "No files found to prune", "No_files_left_to_download": "No files left to download", @@ -3653,8 +3639,6 @@ "No_mentions_found": "No mentions found", "No_mentions": "No mentions", "No_mentions_description": "@{username}, @all, @here mentions and highlighted words will appear here.", - "No_unread_mentions": "No unread mentions", - "No_unread_mentions_description": "Unread @{username}, @all, @here mentions and highlighted words will appear here.", "No_message_reports": "No message reports", "No_messages_found_to_prune": "No messages found to prune", "No_messages_yet": "No messages yet", @@ -3683,8 +3667,6 @@ "No_user_reports": "No user reports", "No_rooms": "No rooms", "No_rooms_description": "@{username}, @all, @here mentions and highlighted words will appear here.", - "No_unread_rooms": "No unread rooms", - "No_unread_rooms_description": "Unread rooms wil appear here.", "Nobody_available": "Nobody available", "Node_version": "Node Version", "None": "None",