Skip to content

Commit fa8413f

Browse files
fix: hide 'Delete all closed chats' button when user lacks remove-closed-livechat-rooms permission (RocketChat#40492)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 89a59b8 commit fa8413f

3 files changed

Lines changed: 92 additions & 14 deletions

File tree

.changeset/ten-lizards-divide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rocket.chat/meteor": patch
3+
---
4+
5+
Fixes issue that displayed the 'Delete all closed chats' button when user lacks `remove-closed-livechat-rooms` permission
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { mockAppRoot } from '@rocket.chat/mock-providers';
2+
import { render, screen } from '@testing-library/react';
3+
import userEvent from '@testing-library/user-event';
4+
5+
import ChatsTableFilter from './ChatsTableFilter';
6+
import type { ChatsContextValue } from '../../contexts/ChatsContext';
7+
8+
jest.mock('../../contexts/ChatsContext', () => ({
9+
useChatsContext: (): ChatsContextValue => ({
10+
filtersQuery: {
11+
guest: '',
12+
servedBy: [],
13+
status: 'all',
14+
department: [],
15+
from: '',
16+
to: '',
17+
tags: [],
18+
units: [],
19+
},
20+
setFiltersQuery: jest.fn(),
21+
resetFiltersQuery: jest.fn(),
22+
displayFilters: {
23+
from: undefined,
24+
to: undefined,
25+
guest: undefined,
26+
servedBy: undefined,
27+
department: undefined,
28+
status: undefined,
29+
tags: undefined,
30+
},
31+
removeFilter: jest.fn(),
32+
hasAppliedFilters: false,
33+
textInputRef: null,
34+
}),
35+
}));
36+
37+
jest.mock('../../hooks/useOmnichannelDirectoryRouter', () => ({
38+
useOmnichannelDirectoryRouter: () => ({
39+
navigate: jest.fn(),
40+
getRouteName: jest.fn(),
41+
}),
42+
}));
43+
44+
describe('ChatsTableFilter', () => {
45+
it('should show the "More" kebab menu when user has "remove-closed-livechat-rooms" permission', async () => {
46+
render(<ChatsTableFilter />, {
47+
wrapper: mockAppRoot().withPermission('remove-closed-livechat-rooms').build(),
48+
});
49+
50+
expect(screen.getByRole('button', { name: 'More' })).toBeInTheDocument();
51+
});
52+
53+
it('should not show the "More" kebab menu when user lacks "remove-closed-livechat-rooms" permission', async () => {
54+
render(<ChatsTableFilter />, {
55+
wrapper: mockAppRoot().build(),
56+
});
57+
58+
expect(screen.queryByRole('button', { name: 'More' })).not.toBeInTheDocument();
59+
});
60+
61+
it('should show "Delete all closed chats" option inside the menu when user has the permission', async () => {
62+
render(<ChatsTableFilter />, {
63+
wrapper: mockAppRoot().withPermission('remove-closed-livechat-rooms').build(),
64+
});
65+
66+
await userEvent.click(screen.getByRole('button', { name: 'More' }));
67+
68+
expect(await screen.findByRole('menuitem', { name: 'Delete_all_closed_chats' })).toBeInTheDocument();
69+
});
70+
});

apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Box, Button, Chip } from '@rocket.chat/fuselage';
22
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
33
import { GenericMenu, GenericModal } from '@rocket.chat/ui-client';
4-
import { useEndpoint, useSetModal, useToastMessageDispatch } from '@rocket.chat/ui-contexts';
4+
import { useEndpoint, usePermission, useSetModal, useToastMessageDispatch } from '@rocket.chat/ui-contexts';
55
import { useQueryClient } from '@tanstack/react-query';
66
import { useTranslation } from 'react-i18next';
77

@@ -16,6 +16,7 @@ const ChatsTableFilter = () => {
1616
const omnichannelDirectoryRouter = useOmnichannelDirectoryRouter();
1717
const queryClient = useQueryClient();
1818
const removeClosedRooms = useEndpoint('POST', '/v1/livechat/rooms.removeAllClosedRooms');
19+
const canRemoveAllClosedChats = usePermission('remove-closed-livechat-rooms');
1920

2021
const { filtersQuery, displayFilters, setFiltersQuery, removeFilter, textInputRef } = useChatsContext();
2122

@@ -35,19 +36,21 @@ const ChatsTableFilter = () => {
3536
setModal(<GenericModal variant='danger' onConfirm={onDeleteAll} onCancel={() => setModal(null)} confirmText={t('Delete')} />);
3637
});
3738

38-
const menuItems = [
39-
{
40-
items: [
39+
const menuItems = canRemoveAllClosedChats
40+
? [
4141
{
42-
id: 'delete-all-closed-chats',
43-
variant: 'danger',
44-
icon: 'trash',
45-
content: t('Delete_all_closed_chats'),
46-
onClick: handleRemoveAllClosed,
47-
} as const,
48-
],
49-
},
50-
];
42+
items: [
43+
{
44+
id: 'delete-all-closed-chats',
45+
variant: 'danger',
46+
icon: 'trash',
47+
content: t('Delete_all_closed_chats'),
48+
onClick: handleRemoveAllClosed,
49+
} as const,
50+
],
51+
},
52+
]
53+
: [];
5154

5255
return (
5356
<>
@@ -67,7 +70,7 @@ const ChatsTableFilter = () => {
6770
>
6871
{t('Filters')}
6972
</Button>
70-
<GenericMenu placement='bottom-end' detached title={t('More')} sections={menuItems} />
73+
{menuItems.length > 0 && <GenericMenu placement='bottom-end' detached title={t('More')} sections={menuItems} />}
7174
</FilterByText>
7275
<Box display='flex' flexWrap='wrap' mbe={4}>
7376
{Object.entries(displayFilters).map(([value, label], index) => {

0 commit comments

Comments
 (0)