diff --git a/apps/meteor/client/components/GenericTable/hooks/usePagination.ts b/apps/meteor/client/components/GenericTable/hooks/usePagination.ts index 803752fda45ef..f7723283fd7ee 100644 --- a/apps/meteor/client/components/GenericTable/hooks/usePagination.ts +++ b/apps/meteor/client/components/GenericTable/hooks/usePagination.ts @@ -5,6 +5,9 @@ import { useItemsPerPage } from './useItemsPerPage'; import { useItemsPerPageLabel } from './useItemsPerPageLabel'; import { useShowingResultsLabel } from './useShowingResultsLabel'; +/** + * TODO: Move `usePagination` outside from `GenericTable` folder + */ export const usePagination = (): { current: ReturnType[0]; setCurrent: ReturnType[1]; diff --git a/apps/meteor/client/views/admin/permissions/PermissionsPage.tsx b/apps/meteor/client/views/admin/permissions/PermissionsPage.tsx index 96c0e9950433a..19f7fbc343206 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsPage.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsPage.tsx @@ -22,8 +22,8 @@ const PermissionsPage = ({ isEnterprise }: { isEnterprise: boolean }): ReactElem const router = useRoute('admin-permissions'); const setModal = useSetModal(); - const paginationProps = usePagination(); - const { permissions, total, roleList } = usePermissionsAndRoles(type, filter, paginationProps.itemsPerPage, paginationProps.current); + const paginationData = usePagination(); + const { permissions, total, roleList } = usePermissionsAndRoles(type, filter, paginationData.itemsPerPage, paginationData.current); const handlePermissionsTab = useEffectEvent(() => { if (type === 'permissions') { @@ -84,7 +84,7 @@ const PermissionsPage = ({ isEnterprise }: { isEnterprise: boolean }): ReactElem permissions={permissions} total={total} setFilter={setFilter} - paginationProps={paginationProps} + paginationData={paginationData} /> diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.spec.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.spec.tsx index c1116b09798cc..9b2bdb4f63eb9 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.spec.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.spec.tsx @@ -7,6 +7,7 @@ import { axe } from 'jest-axe'; import PermissionsTable from './PermissionsTable'; import * as stories from './PermissionsTable.stories'; +import { createMockedPagination } from '../../../../../tests/mocks/data'; const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName || 'Story', Story]); @@ -24,6 +25,8 @@ test.each(testCases)('%s should have no a11y violations', async (_storyname, Sto expect(results).toHaveNoViolations(); }); +const paginationData = createMockedPagination(); + const defaultPermissions: IPermission[] = [ { _id: 'access-permissions', @@ -51,7 +54,13 @@ const roles: IRole[] = [ test('should display modal if the permission is access-permissions and has only one granted role', async () => { render( - undefined} roleList={roles} />, + undefined} + roleList={roles} + paginationData={paginationData} + />, { wrapper: mockAppRoot().build(), }, @@ -70,9 +79,18 @@ test('should NOT display modal if the permission is access-permissions and has m }, ]; - render( undefined} roleList={roles} />, { - wrapper: mockAppRoot().build(), - }); + render( + undefined} + roleList={roles} + paginationData={paginationData} + />, + { + wrapper: mockAppRoot().build(), + }, + ); await userEvent.click(screen.getByRole('checkbox', { name: 'access-permissions - Administrator' })); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.stories.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.stories.tsx index c553c19f36fb3..029283b814b0c 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.stories.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.stories.tsx @@ -3,6 +3,7 @@ import { Margins } from '@rocket.chat/fuselage'; import type { Meta, StoryFn } from '@storybook/react'; import PermissionsTable from './PermissionsTable'; +import { createMockedPagination } from '../../../../../tests/mocks/data'; import { PageContent } from '../../../../components/Page'; export default { @@ -98,18 +99,24 @@ const permissions: IPermission[] = [ }, ]; -export const Default: StoryFn = (args) => ; +const paginationData = createMockedPagination(permissions.length, 10); + +const Template: StoryFn = (args) => ; + +export const Default = Template.bind({}); Default.args = { - total: permissions.length, + total: 10, permissions, roleList: roles, setFilter: () => undefined, + paginationData, }; -export const Empty: StoryFn = (args) => ; +export const Empty = Template.bind({}); Empty.args = { total: 0, permissions: [], roleList: [], setFilter: () => undefined, + paginationData, }; diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx index e034adfcf1f46..b2aede0e32d9f 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx @@ -16,15 +16,17 @@ type PermissionsTableProps = { permissions: IPermission[]; setFilter: (filter: string) => void; total: number; - paginationProps?: ReturnType; + paginationData: ReturnType; }; -const PermissionsTable = ({ roleList, permissions, setFilter, total, paginationProps }: PermissionsTableProps) => { +const PermissionsTable = ({ roleList, permissions, setFilter, total, paginationData }: PermissionsTableProps) => { const { t } = useTranslation(); const grantRole = useMethod('authorization:addPermissionToRole'); const removeRole = useMethod('authorization:removeRoleFromPermission'); + const { current, itemsPerPage, setCurrent, setItemsPerPage, ...paginationProps } = paginationData; + const tableCustomStyle = css` // Makes the first column of the table sticky tr > th { @@ -77,9 +79,11 @@ const PermissionsTable = ({ roleList, permissions, setFilter, total, paginationP diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/__snapshots__/PermissionsTable.spec.tsx.snap b/apps/meteor/client/views/admin/permissions/PermissionsTable/__snapshots__/PermissionsTable.spec.tsx.snap index 397abc9b43e5d..88fbb2b696bf2 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/__snapshots__/PermissionsTable.spec.tsx.snap +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/__snapshots__/PermissionsTable.spec.tsx.snap @@ -1100,7 +1100,7 @@ exports[`renders Default without crashing 1`] = ` - Showing results 1 - 4 of 4 + Showing results 1 - 4 of 10
    { - const t = useTranslation(); + const { t } = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); const queryClient = useQueryClient(); @@ -54,6 +57,28 @@ const UsersInRolePage = ({ role }: { role: IRole }): ReactElement => { } }); + const getUsersInRoleEndpoint = useEndpoint('GET', '/v1/roles.getUsersInRole'); + + const paginationData = usePagination(); + const { itemsPerPage, current } = paginationData; + + const query = useMemo( + () => ({ + role: _id, + ...(rid && { roomId: rid }), + ...(itemsPerPage && { count: itemsPerPage }), + ...(current && { offset: current }), + }), + [itemsPerPage, current, rid, _id], + ); + + const { data, isLoading, isSuccess, refetch, isError } = useQuery({ + queryKey: ['getUsersInRole', _id, query], + queryFn: async () => getUsersInRoleEndpoint(query), + }); + + const handleRemove = useRemoveUserFromRole({ rid, roleId: _id, roleName: name, roleDescription: description }); + return ( @@ -127,7 +152,18 @@ const UsersInRolePage = ({ role }: { role: IRole }): ReactElement => { - {(role.scope === 'Users' || rid) && } + {(role.scope === 'Users' || rid) && ( + + )} {role.scope !== 'Users' && !rid && {t('Select_a_room')}} diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.spec.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.spec.tsx new file mode 100644 index 0000000000000..87aa750f8aba1 --- /dev/null +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.spec.tsx @@ -0,0 +1,21 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { composeStories } from '@storybook/react'; +import { render } from '@testing-library/react'; +import { axe } from 'jest-axe'; + +import * as stories from './UsersInRoleTable.stories'; + +const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName || 'Story', Story]); + +test.each(testCases)(`renders %s without crashing`, async (_storyname, Story) => { + const { baseElement } = render(, { wrapper: mockAppRoot().build() }); + expect(baseElement).toMatchSnapshot(); +}); + +test.each(testCases)('%s should have no a11y violations', async (_storyname, Story) => { + const { container } = render(, { wrapper: mockAppRoot().build() }); + + // TODO: Needed to skip `button-name` because fuselage‘s `Pagination` buttons are missing names + const results = await axe(container, { rules: { 'button-name': { enabled: false } } }); + expect(results).toHaveNoViolations(); +}); diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.stories.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.stories.tsx new file mode 100644 index 0000000000000..68ee23235d350 --- /dev/null +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.stories.tsx @@ -0,0 +1,84 @@ +import { Margins } from '@rocket.chat/fuselage'; +import type { Meta, StoryFn } from '@storybook/react'; + +import UsersInRoleTable from './UsersInRoleTable'; +import { createMockedPagination } from '../../../../../../tests/mocks/data'; +import { PageContent } from '../../../../../components/Page'; + +export default { + component: UsersInRoleTable, + decorators: [ + (fn) => ( + + {fn()} + + ), + ], +} satisfies Meta; + +const generateMockedUsers = (count: number) => + Array.from({ length: count }, (_, i) => ({ + _id: `${i + 1}`, + username: `user.${i + 1}`, + name: `User ${i + 1}`, + emails: [{ address: `user${i + 1}@example.com`, verified: i % 2 === 0 }], + createdAt: new Date().toISOString(), + _updatedAt: new Date().toISOString(), + roles: [i < 5 ? 'admin' : 'user'], + type: 'user', + active: true, + })); + +const mockedUsers = generateMockedUsers(5); + +const paginationData = createMockedPagination(mockedUsers.length, 30); + +const Template: StoryFn = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + total: 30, + isLoading: false, + isError: false, + isSuccess: true, + users: mockedUsers, + onRemove: () => undefined, + refetch: () => undefined, + paginationData, +}; + +export const withLoading = Template.bind({}); +withLoading.args = { + total: 0, + isLoading: true, + isError: false, + isSuccess: false, + users: [], + onRemove: () => undefined, + refetch: () => undefined, + paginationData, +}; + +export const withNoResults = Template.bind({}); +withNoResults.args = { + total: 0, + isLoading: false, + isError: false, + isSuccess: true, + users: [], + onRemove: () => undefined, + refetch: () => undefined, + paginationData, +}; + +export const withError = Template.bind({}); +withError.args = { + total: 0, + isLoading: false, + isError: true, + isSuccess: false, + users: [], + onRemove: () => undefined, + refetch: () => undefined, + paginationData, +}; diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx index 3695f4ef61490..974120d00e67f 100644 --- a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx @@ -1,11 +1,5 @@ -import type { IRole, IRoom, IUserInRole } from '@rocket.chat/core-typings'; +import type { IUserInRole, Serialized } from '@rocket.chat/core-typings'; import { Pagination } from '@rocket.chat/fuselage'; -import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; -import { GenericModal } from '@rocket.chat/ui-client'; -import { useSetModal, useToastMessageDispatch, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; -import type { ReactElement } from 'react'; -import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import UsersInRoleTableRow from './UsersInRoleTableRow'; @@ -18,78 +12,28 @@ import { GenericTableBody, GenericTableLoadingTable, } from '../../../../../components/GenericTable'; -import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; +import type { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; type UsersInRoleTableProps = { - roleName: IRole['name']; - roleId: IRole['_id']; - description: IRole['description']; - rid?: IRoom['_id']; + isLoading: boolean; + isError: boolean; + isSuccess: boolean; + total: number; + users: Serialized[]; + onRemove: (username: IUserInRole['username']) => void; + paginationData: ReturnType; + refetch: () => void; }; -const UsersInRoleTable = ({ rid, roleId, roleName, description }: UsersInRoleTableProps): ReactElement => { +const UsersInRoleTable = ({ isLoading, isSuccess, isError, total, users, onRemove, refetch, paginationData }: UsersInRoleTableProps) => { const { t } = useTranslation(); - const setModal = useSetModal(); - const dispatchToastMessage = useToastMessageDispatch(); - const queryClient = useQueryClient(); - - const getUsersInRoleEndpoint = useEndpoint('GET', '/v1/roles.getUsersInRole'); - const removeUserFromRoleEndpoint = useEndpoint('POST', '/v1/roles.removeUserFromRole'); - - const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); - - const query = useMemo( - () => ({ - role: roleId, - ...(rid && { roomId: rid }), - ...(itemsPerPage && { count: itemsPerPage }), - ...(current && { offset: current }), - }), - [itemsPerPage, current, rid, roleId], - ); - - const { data, isLoading, isSuccess, refetch, isError } = useQuery({ - queryKey: ['getUsersInRole', roleId, query], - - queryFn: async () => getUsersInRoleEndpoint(query), - }); - - const users = - data?.users?.map((user) => ({ - ...user, - createdAt: new Date(user.createdAt), - _updatedAt: new Date(user._updatedAt), - })) || []; - - const handleRemove = useEffectEvent((username: IUserInRole['username']) => { - const remove = async () => { - try { - if (!username) throw new Error('Username is required'); - - await removeUserFromRoleEndpoint({ roleId, username, scope: rid }); - dispatchToastMessage({ type: 'success', message: t('User_removed') }); - queryClient.invalidateQueries({ - queryKey: ['getUsersInRole'], - }); - } catch (error) { - dispatchToastMessage({ type: 'error', message: error }); - } finally { - setModal(null); - } - }; - - setModal( - setModal(null)} confirmText={t('Delete')}> - {t('The_user_s_will_be_removed_from_role_s', { postProcess: 'sprintf', sprintf: [username, description || roleName] })} - , - ); - }); + const { current, itemsPerPage, setCurrent, setItemsPerPage, ...paginationProps } = paginationData; const headers = ( <> {t('Name')} {t('Email')} - + {t('Actions')} ); @@ -99,7 +43,7 @@ const UsersInRoleTable = ({ rid, roleId, roleName, description }: UsersInRoleTab {headers} - + )} @@ -108,21 +52,23 @@ const UsersInRoleTable = ({ rid, roleId, roleName, description }: UsersInRoleTab {headers} - {users?.map((user) => )} + {users.map((user) => ( + + ))} )} - {users?.length === 0 && } + {isSuccess && users?.length === 0 && } {isError && } ); diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx index e1c9b789234cf..00e24d820893f 100644 --- a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx @@ -1,4 +1,4 @@ -import type { IUserInRole } from '@rocket.chat/core-typings'; +import type { IUserInRole, Serialized } from '@rocket.chat/core-typings'; import { Box, IconButton } from '@rocket.chat/fuselage'; import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; import { UserAvatar } from '@rocket.chat/ui-avatar'; @@ -10,7 +10,7 @@ import { getUserEmailAddress } from '../../../../../../lib/getUserEmailAddress'; import { GenericTableRow, GenericTableCell } from '../../../../../components/GenericTable'; type UsersInRoleTableRowProps = { - user: IUserInRole; + user: Serialized; onRemove: (username: IUserInRole['username']) => void; }; diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/__snapshots__/UsersInRoleTable.spec.tsx.snap b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/__snapshots__/UsersInRoleTable.spec.tsx.snap new file mode 100644 index 0000000000000..33863533c185e --- /dev/null +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/__snapshots__/UsersInRoleTable.spec.tsx.snap @@ -0,0 +1,1104 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`renders Default without crashing 1`] = ` + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + Name +
    +
    +
    + Email +
    +
    +
    + Actions +
    +
    +
    +
    + +
    +
    +
    + User 1 +
    +
    + @user.1 +
    +
    +
    +
    + user1@example.com + + +
    +
    +
    + +
    +
    +
    + User 2 +
    +
    + @user.2 +
    +
    +
    +
    + user2@example.com + + +
    +
    +
    + +
    +
    +
    + User 3 +
    +
    + @user.3 +
    +
    +
    +
    + user3@example.com + + +
    +
    +
    + +
    +
    +
    + User 4 +
    +
    + @user.4 +
    +
    +
    +
    + user4@example.com + + +
    +
    +
    + +
    +
    +
    + User 5 +
    +
    + @user.5 +
    +
    +
    +
    + user5@example.com + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + +`; + +exports[`renders withError without crashing 1`] = ` + +
    +
    +
    +
    + +

    + Something_went_wrong +

    +
    + +
    +
    +
    +
    +
    + +`; + +exports[`renders withLoading without crashing 1`] = ` + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + Name +
    +
    +
    + Email +
    +
    +
    + Actions +
    +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +`; + +exports[`renders withNoResults without crashing 1`] = ` + +
    +
    +
    +
    + +

    + No_results_found +

    +
    +
    +
    +
    + +`; diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/hooks/useRemoveUserFromRole.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/hooks/useRemoveUserFromRole.tsx new file mode 100644 index 0000000000000..14d188058246a --- /dev/null +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/hooks/useRemoveUserFromRole.tsx @@ -0,0 +1,52 @@ +import type { IRole, IRoom, IUserInRole } from '@rocket.chat/core-typings'; +import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; +import { GenericModal } from '@rocket.chat/ui-client'; +import { useSetModal, useToastMessageDispatch, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; + +export const useRemoveUserFromRole = ({ + rid, + roleId, + roleName, + roleDescription, +}: { + rid?: IRoom['_id']; + roleId: IRole['_id']; + roleName: IRole['name']; + roleDescription: IRole['description']; +}) => { + const { t } = useTranslation(); + + const setModal = useSetModal(); + const dispatchToastMessage = useToastMessageDispatch(); + const queryClient = useQueryClient(); + + const removeUserFromRoleEndpoint = useEndpoint('POST', '/v1/roles.removeUserFromRole'); + + const handleRemove = useEffectEvent((username: IUserInRole['username']) => { + const remove = async () => { + try { + if (!username) throw new Error('Username is required'); + + await removeUserFromRoleEndpoint({ roleId, username, scope: rid }); + dispatchToastMessage({ type: 'success', message: t('User_removed') }); + queryClient.invalidateQueries({ + queryKey: ['getUsersInRole'], + }); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + } finally { + setModal(null); + } + }; + + setModal( + setModal(null)} confirmText={t('Delete')}> + {t('The_user_s_will_be_removed_from_role_s', { postProcess: 'sprintf', sprintf: [username, roleDescription || roleName] })} + , + ); + }); + + return handleRemove; +}; diff --git a/apps/meteor/client/views/admin/users/UsersTable/UsersTable.stories.tsx b/apps/meteor/client/views/admin/users/UsersTable/UsersTable.stories.tsx index 69a44435b5d00..8be522d6143b3 100644 --- a/apps/meteor/client/views/admin/users/UsersTable/UsersTable.stories.tsx +++ b/apps/meteor/client/views/admin/users/UsersTable/UsersTable.stories.tsx @@ -2,85 +2,83 @@ import { UserStatus } from '@rocket.chat/core-typings'; import type { Meta, StoryFn } from '@storybook/react'; import UsersTable from './UsersTable'; +import { createMockedPagination } from '../../../../../tests/mocks/data'; export default { component: UsersTable, } satisfies Meta; -const mockedPagination = { - current: 0, - setCurrent: () => undefined, - itemsPerPage: 25 as const, - setItemsPerPage: () => undefined, - itemsPerPageLabel: () => 'Items per page:', - showingResultsLabel: () => 'Showing results 1 - 5 of 5', -}; +const Template: StoryFn = (args) => ; + +const mockedUsers = [ + { + _id: '1', + username: 'example.user', + name: 'Example User', + emails: [{ address: 'example@rocket.chat', verified: true }], + status: UserStatus.ONLINE, + roles: ['user'], + active: true, + type: '', + }, + { + _id: '2', + username: 'john.doe', + name: 'John Doe', + emails: [{ address: 'john@rocket.chat', verified: true }], + status: UserStatus.OFFLINE, + roles: ['admin', 'user'], + active: true, + type: '', + }, + { + _id: '3', + username: 'sarah.smith', + name: 'Sarah Smith', + emails: [{ address: 'sarah@rocket.chat', verified: true }], + status: UserStatus.AWAY, + roles: ['user'], + active: true, + type: '', + }, + { + _id: '4', + username: 'mike.wilson', + name: 'Mike Wilson', + emails: [{ address: 'mike@rocket.chat', verified: false }], + status: UserStatus.BUSY, + roles: ['user'], + active: true, + type: '', + }, + { + _id: '5', + username: 'emma.davis', + name: 'Emma Davis', + emails: [{ address: 'emma@rocket.chat', verified: true }], + status: UserStatus.ONLINE, + roles: ['moderator', 'user'], + active: true, + type: '', + }, +]; -const Template: StoryFn = (args) => ; +const paginationData = createMockedPagination(mockedUsers.length, 5); export const Default = Template.bind({}); Default.args = { - users: [ - { - _id: '1', - username: 'example.user', - name: 'Example User', - emails: [{ address: 'example@rocket.chat', verified: true }], - status: UserStatus.ONLINE, - roles: ['user'], - active: true, - type: '', - }, - { - _id: '2', - username: 'john.doe', - name: 'John Doe', - emails: [{ address: 'john@rocket.chat', verified: true }], - status: UserStatus.OFFLINE, - roles: ['admin', 'user'], - active: true, - type: '', - }, - { - _id: '3', - username: 'sarah.smith', - name: 'Sarah Smith', - emails: [{ address: 'sarah@rocket.chat', verified: true }], - status: UserStatus.AWAY, - roles: ['user'], - active: true, - type: '', - }, - { - _id: '4', - username: 'mike.wilson', - name: 'Mike Wilson', - emails: [{ address: 'mike@rocket.chat', verified: false }], - status: UserStatus.BUSY, - roles: ['user'], - active: true, - type: '', - }, - { - _id: '5', - username: 'emma.davis', - name: 'Emma Davis', - emails: [{ address: 'emma@rocket.chat', verified: true }], - status: UserStatus.ONLINE, - roles: ['moderator', 'user'], - active: true, - type: '', - }, - ], + users: mockedUsers, total: 5, isLoading: false, isSuccess: true, tab: 'all', + paginationData, }; export const Loading = Template.bind({}); Loading.args = { isLoading: true, + paginationData, }; export const NoResults = Template.bind({}); @@ -90,4 +88,5 @@ NoResults.args = { isLoading: false, isError: false, isSuccess: true, + paginationData, }; diff --git a/apps/meteor/tests/mocks/data.ts b/apps/meteor/tests/mocks/data.ts index 8e4083a1d3219..1dde2432ca3be 100644 --- a/apps/meteor/tests/mocks/data.ts +++ b/apps/meteor/tests/mocks/data.ts @@ -453,3 +453,12 @@ export function createFakeMonitor(overrides?: Partial ({ + current: 0, + setCurrent: () => undefined, + itemsPerPage: 25 as const, + setItemsPerPage: () => undefined, + itemsPerPageLabel: () => 'Items per page:', + showingResultsLabel: () => `Showing results 1 - ${results} of ${total}`, +});