apps/meteor/client/views/admin/integrations/IntegrationsTable.tsx
import { Pagination, States, StatesActions, StatesAction, StatesIcon, StatesTitle } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import { useEndpoint, useRoute, useTranslation, useLayout } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import React, { useMemo, useCallback, useState } from 'react';
import FilterByText from '../../../components/FilterByText';
import GenericNoResults from '../../../components/GenericNoResults';
import {
GenericTable,
GenericTableBody,
GenericTableHeader,
GenericTableHeaderCell,
GenericTableLoadingTable,
} from '../../../components/GenericTable';
import { usePagination } from '../../../components/GenericTable/hooks/usePagination';
import { useSort } from '../../../components/GenericTable/hooks/useSort';
import IntegrationRow from './IntegrationRow';
const IntegrationsTable = ({ type }: { type?: string }) => {
const t = useTranslation();
const { isMobile } = useLayout();
const [text, setText] = useState('');
const router = useRoute('admin-integrations');
const { sortBy, sortDirection, setSort } = useSort<'name' | 'channel' | '_createdBy' | '_createdAt' | 'username'>('name');
const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination();
const query = useDebouncedValue(
useMemo(
() => ({
query: JSON.stringify({ name: { $regex: escapeRegExp(text), $options: 'i' }, type }),
sort: `{ "${sortBy}": ${sortDirection === 'asc' ? 1 : -1} }`,
count: itemsPerPage,
offset: current,
}),
[text, itemsPerPage, current, sortBy, sortDirection, type],
),
500,
);
const getIntegrations = useEndpoint('GET', '/v1/integrations.list');
const { data, isLoading, isSuccess, isError, refetch } = useQuery(['integrations', query], async () => getIntegrations(query));
const onClick = useCallback(
(_id, type) => () =>
router.push({
context: 'edit',
type: type === 'webhook-incoming' ? 'incoming' : 'outgoing',
id: _id,
}),
[router],
);
const headers = (
<>
<GenericTableHeaderCell
key='name'
direction={sortDirection}
active={sortBy === 'name'}
onClick={setSort}
sort='name'
{...(!isMobile && { w: 'x280' })}
>
{t('Name')}
</GenericTableHeaderCell>
<GenericTableHeaderCell key='channel' direction={sortDirection} active={sortBy === 'channel'} onClick={setSort} sort='channel'>
{t('Post_to')}
</GenericTableHeaderCell>
<GenericTableHeaderCell
key='_createdBy'
direction={sortDirection}
active={sortBy === '_createdBy'}
onClick={setSort}
sort='_createdBy'
>
{t('Created_by')}
</GenericTableHeaderCell>
{!isMobile && (
<GenericTableHeaderCell
key='_createdAt'
direction={sortDirection}
active={sortBy === '_createdAt'}
onClick={setSort}
sort='_createdAt'
>
{t('Created_at')}
</GenericTableHeaderCell>
)}
<GenericTableHeaderCell key='username' direction={sortDirection} active={sortBy === 'username'} onClick={setSort} sort='username'>
{t('Post_as')}
</GenericTableHeaderCell>
</>
);
return (
<>
<FilterByText placeholder={t('Search_Integrations')} onChange={setText} />
{isLoading && (
<GenericTable>
<GenericTableHeader>{headers}</GenericTableHeader>
<GenericTableBody>
<GenericTableLoadingTable headerCells={!isMobile ? 5 : 4} />
</GenericTableBody>
</GenericTable>
)}
{isSuccess && data && data.integrations.length > 0 && (
<>
<GenericTable aria-label={t('Integrations_table')}>
<GenericTableHeader>{headers}</GenericTableHeader>
<GenericTableBody>
{isSuccess &&
data?.integrations.map((integration) => (
<IntegrationRow key={integration._id} integration={integration} isMobile={isMobile} onClick={onClick} />
))}
</GenericTableBody>
</GenericTable>
<Pagination
divider
current={current}
itemsPerPage={itemsPerPage}
count={data?.total || 0}
onSetItemsPerPage={onSetItemsPerPage}
onSetCurrent={onSetCurrent}
{...paginationProps}
/>
</>
)}
{isSuccess && data && data.integrations.length === 0 && <GenericNoResults />}
{isError && (
<States>
<StatesIcon name='warning' variation='danger' />
<StatesTitle>{t('Something_went_wrong')}</StatesTitle>
<StatesActions>
<StatesAction onClick={() => refetch()}>{t('Reload_page')}</StatesAction>
</StatesActions>
</States>
)}
</>
);
};
export default IntegrationsTable;