diff --git a/client/components/GenericTable/index.js b/client/components/GenericTable/GenericTable.tsx similarity index 60% rename from client/components/GenericTable/index.js rename to client/components/GenericTable/GenericTable.tsx index e606a43ae64..6e7fcf57f7a 100644 --- a/client/components/GenericTable/index.js +++ b/client/components/GenericTable/GenericTable.tsx @@ -1,34 +1,67 @@ import { Box, Pagination, Table, Tile } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import React, { useState, useEffect, useCallback, forwardRef } from 'react'; +import React, { + useState, + useEffect, + useCallback, + forwardRef, + ReactNode, + ReactElement, + Key, + RefAttributes, +} from 'react'; import flattenChildren from 'react-keyed-flatten-children'; import { useTranslation } from '../../contexts/TranslationContext'; import ScrollableContentWrapper from '../ScrollableContentWrapper'; -import HeaderCell from './HeaderCell'; import LoadingRow from './LoadingRow'; -const GenericTable = ( +const defaultParamsValue = { text: '', current: 0, itemsPerPage: 25 } as const; +const defaultSetParamsValue = (): void => undefined; + +type Params = { text?: string; current?: number; itemsPerPage?: 25 | 50 | 100 }; + +type GenericTableProps< + FilterProps extends { onChange?: (params: Params) => void }, + ResultProps extends { _id?: Key }, +> = { + fixed?: boolean; + header?: ReactNode; + params?: Params; + setParams?: (params: Params) => void; + children?: (props: ResultProps, key: number) => ReactElement; + renderFilter?: (props: FilterProps) => ReactElement; + renderRow?: (props: ResultProps) => ReactElement; + results?: ResultProps[]; + total?: number; + pagination?: boolean; +} & FilterProps; + +const GenericTable: { + void }, ResultProps extends { _id?: Key }>( + props: GenericTableProps & RefAttributes, + ): ReactElement | null; +} = forwardRef(function GenericTable( { children, fixed = true, header, - params: paramsDefault = '', + params: paramsDefault = defaultParamsValue, + setParams = defaultSetParamsValue, renderFilter, renderRow: RenderRow, results, - setParams = () => {}, total, pagination = true, ...props }, ref, -) => { +) { const t = useTranslation(); const [filter, setFilter] = useState(paramsDefault); - const [itemsPerPage, setItemsPerPage] = useState(25); + const [itemsPerPage, setItemsPerPage] = useState<25 | 50 | 100>(25); const [current, setCurrent] = useState(0); @@ -40,7 +73,13 @@ const GenericTable = ( const Loading = useCallback(() => { const headerCells = flattenChildren(header); - return Array.from({ length: 10 }, (_, i) => ); + return ( + <> + {Array.from({ length: 10 }, (_, i) => ( + + ))} + + ); }, [header]); const showingResultsLabel = useCallback( @@ -53,7 +92,9 @@ const GenericTable = ( return ( <> - {typeof renderFilter === 'function' ? renderFilter({ onChange: setFilter, ...props }) : null} + {typeof renderFilter === 'function' + ? renderFilter({ ...props, onChange: setFilter } as any) // TODO: ugh + : null} {results && !results.length ? ( {t('No_data_found')} @@ -98,8 +139,6 @@ const GenericTable = ( )} ); -}; - -export default Object.assign(forwardRef(GenericTable), { - HeaderCell, }); + +export default GenericTable; diff --git a/client/components/GenericTable/index.ts b/client/components/GenericTable/index.ts new file mode 100644 index 00000000000..8da6df3fc14 --- /dev/null +++ b/client/components/GenericTable/index.ts @@ -0,0 +1,6 @@ +import GenericTable from './GenericTable'; +import HeaderCell from './HeaderCell'; + +export default Object.assign(GenericTable, { + HeaderCell, +}); diff --git a/client/views/teams/ChannelDesertionTable.tsx b/client/views/teams/ChannelDesertionTable.tsx index dfa1401abe0..8aeb8db3067 100644 --- a/client/views/teams/ChannelDesertionTable.tsx +++ b/client/views/teams/ChannelDesertionTable.tsx @@ -66,11 +66,11 @@ const ChannelDesertionTable: FC = ({ fixed={false} pagination={false} > - {(room: IRoom, key: string): ReactElement => ( + {(room, key): ReactElement => ( { ? moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(7, 'days').utc() : moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(7, 'days'), end: utc - ? moment.utc().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(1, 'days').utc() + ? moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(1, 'days').utc() : moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(1, 'days'), }; @@ -45,7 +45,7 @@ const NewUsersSection = ({ timezone }) => { ? moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(30, 'days').utc() : moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(30, 'days'), end: utc - ? moment.utc().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(1, 'days').utc() + ? moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(1, 'days').utc() : moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(1, 'days'), }; @@ -209,11 +209,10 @@ const NewUsersSection = ({ timezone }) => { }, }, tooltip: { - container: { - backgroundColor: '#1F2329', - boxShadow: '0px 0px 12px rgba(47, 52, 61, 0.12), 0px 0px 2px rgba(47, 52, 61, 0.08)', - borderRadius: 2, - }, + backgroundColor: '#1F2329', + boxShadow: '0px 0px 12px rgba(47, 52, 61, 0.12), 0px 0px 2px rgba(47, 52, 61, 0.08)', + borderRadius: 2, + padding: 4, }, }} tooltip={({ value, indexValue }) => diff --git a/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx b/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx index bffe03b0de9..6cf4d2a1364 100644 --- a/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx +++ b/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx @@ -1,6 +1,6 @@ import { Button, Icon, ButtonGroup } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import React, { FC, ReactNode, ReactElement, Dispatch, SetStateAction } from 'react'; +import React, { FC, ReactElement, Dispatch, SetStateAction } from 'react'; import GenericTable from '../../../../client/components/GenericTable'; import NoResults from '../../../../client/components/GenericTable/NoResults'; @@ -11,11 +11,11 @@ import { useTranslation } from '../../../../client/contexts/TranslationContext'; export type CannedResponsesPageProps = { data: any; header: ReactElement[]; - setParams: Dispatch>; - params: { current: number; itemsPerPage: number }; + setParams: Dispatch>; + params: { current?: number; itemsPerPage?: 25 | 50 | 100 }; title: string; - renderRow: ReactNode | null; - renderFilter: FC; + renderFilter?: (props: any) => ReactElement; + renderRow?: (props: any) => ReactElement; totalCannedResponses: number; }; diff --git a/ee/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx b/ee/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx index 3267ec484a7..0b4dc7f016d 100644 --- a/ee/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx +++ b/ee/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx @@ -1,6 +1,6 @@ import { Table, Box } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import React, { useMemo, useCallback, useState, FC, ReactNode, ReactElement } from 'react'; +import React, { useMemo, useCallback, useState, FC, ReactElement } from 'react'; import GenericTable from '../../../../client/components/GenericTable'; import NotAuthorizedPage from '../../../../client/components/NotAuthorizedPage'; @@ -43,7 +43,10 @@ const CannedResponsesRoute: FC = () => { const { sharing, createdBy, tags, text } = values as CannedResponseFilterValues; const { handleSharing, handleCreatedBy, handleTags, handleText } = handlers; - const [params, setParams] = useState({ current: 0, itemsPerPage: 25 }); + const [params, setParams] = useState<{ current?: number; itemsPerPage?: 25 | 50 | 100 }>({ + current: 0, + itemsPerPage: 25, + }); const [sort, setSort] = useState<[string, 'asc' | 'desc' | undefined]>(['shortcut', 'asc']); const debouncedParams = useDebouncedValue(params, 500); @@ -159,7 +162,7 @@ const CannedResponsesRoute: FC = () => { ); const renderRow = useCallback( - ({ _id, shortcut, scope, createdBy, createdAt, tags = [] }): ReactNode => ( + ({ _id, shortcut, scope, createdBy, createdAt, tags = [] }): ReactElement => (