From ca78c46c38ea51004d35496c09d17f1bb9195629 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 18 Nov 2021 03:01:52 -0300 Subject: [PATCH 1/4] New Generic Table and Custom Emojis Table --- client/components/FilterByText.tsx | 21 ++-- .../components/GenericTable/GenericTable.tsx | 95 ++++++-------- .../GenericTable/V2/GenericTable.tsx | 25 ++++ .../GenericTable/V2/GenericTableBody.tsx | 4 + .../GenericTable/V2/GenericTableCell.tsx | 6 + .../GenericTable/V2/GenericTableHeader.tsx | 10 ++ .../V2/GenericTableHeaderCell.tsx | 30 +++++ .../V2/GenericTableLoadingRow.tsx | 25 ++++ .../V2/GenericTableLoadingTable.tsx | 15 +++ .../GenericTable/V2/GenericTableRow.tsx | 6 + .../GenericTable/hooks/useCurrent.ts | 9 ++ .../GenericTable/hooks/useItemsPerPage.ts | 11 ++ .../hooks/useItemsPerPageLabel.ts | 8 ++ .../GenericTable/hooks/usePagination.ts | 30 +++++ .../hooks/useShowingResultsLabel.ts | 19 +++ .../components/GenericTable/hooks/useSort.ts | 34 +++++ client/components/GenericTable/index.ts | 9 ++ client/views/admin/customEmoji/CustomEmoji.js | 65 ---------- .../views/admin/customEmoji/CustomEmoji.tsx | 119 ++++++++++++++++++ .../admin/customEmoji/CustomEmojiRoute.js | 45 +------ definition/rest/v1/emojiCustom.ts | 34 +++-- 21 files changed, 437 insertions(+), 183 deletions(-) create mode 100644 client/components/GenericTable/V2/GenericTable.tsx create mode 100644 client/components/GenericTable/V2/GenericTableBody.tsx create mode 100644 client/components/GenericTable/V2/GenericTableCell.tsx create mode 100644 client/components/GenericTable/V2/GenericTableHeader.tsx create mode 100644 client/components/GenericTable/V2/GenericTableHeaderCell.tsx create mode 100644 client/components/GenericTable/V2/GenericTableLoadingRow.tsx create mode 100644 client/components/GenericTable/V2/GenericTableLoadingTable.tsx create mode 100644 client/components/GenericTable/V2/GenericTableRow.tsx create mode 100644 client/components/GenericTable/hooks/useCurrent.ts create mode 100644 client/components/GenericTable/hooks/useItemsPerPage.ts create mode 100644 client/components/GenericTable/hooks/useItemsPerPageLabel.ts create mode 100644 client/components/GenericTable/hooks/usePagination.ts create mode 100644 client/components/GenericTable/hooks/useShowingResultsLabel.ts create mode 100644 client/components/GenericTable/hooks/useSort.ts delete mode 100644 client/views/admin/customEmoji/CustomEmoji.js create mode 100644 client/views/admin/customEmoji/CustomEmoji.tsx diff --git a/client/components/FilterByText.tsx b/client/components/FilterByText.tsx index 0c06774c6e6dc..170c0c1944adb 100644 --- a/client/components/FilterByText.tsx +++ b/client/components/FilterByText.tsx @@ -6,19 +6,22 @@ import { useTranslation } from '../contexts/TranslationContext'; type FilterByTextProps = { placeholder?: string; onChange: (filter: { text: string }) => void; - displayButton: boolean; + inputRef?: () => void; +}; + +type FilterByTextPropsWithButton = FilterByTextProps & { + displayButton: true; textButton: string; onButtonClick: () => void; - inputRef: () => void; }; +const isFilterByTextPropsWithButton = (props: any): props is FilterByTextPropsWithButton => + 'displayButton' in props && props.displayButton === true; const FilterByText: FC = ({ placeholder, onChange: setFilter, - displayButton: display = false, - textButton = '', - onButtonClick, inputRef, + children: _, ...props }) => { const t = useTranslation(); @@ -53,9 +56,11 @@ const FilterByText: FC = ({ onChange={handleInputChange} value={text} /> - + {isFilterByTextPropsWithButton(props) && ( + + )} ); }; diff --git a/client/components/GenericTable/GenericTable.tsx b/client/components/GenericTable/GenericTable.tsx index 99124d8186fd5..a345475107519 100644 --- a/client/components/GenericTable/GenericTable.tsx +++ b/client/components/GenericTable/GenericTable.tsx @@ -1,20 +1,23 @@ -import { Box, Pagination, Table, Tile } from '@rocket.chat/fuselage'; +import { Pagination, Tile } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import React, { useState, useEffect, - useCallback, forwardRef, ReactNode, ReactElement, Key, - RefAttributes, + useMemo, + Ref, } from 'react'; import flattenChildren from 'react-keyed-flatten-children'; import { useTranslation } from '../../contexts/TranslationContext'; -import ScrollableContentWrapper from '../ScrollableContentWrapper'; -import LoadingRow from './LoadingRow'; +import { GenericTable as GenericTableV2 } from './V2/GenericTable'; +import { GenericTableBody } from './V2/GenericTableBody'; +import { GenericTableHeader } from './V2/GenericTableHeader'; +import { GenericTableLoadingTable } from './V2/GenericTableLoadingTable'; +import { usePagination } from './hooks/usePagination'; const defaultParamsValue = { text: '', current: 0, itemsPerPage: 25 } as const; const defaultSetParamsValue = (): void => undefined; @@ -37,14 +40,10 @@ type GenericTableProps< pagination?: boolean; } & FilterProps; -const GenericTable: { - < - FilterProps extends { onChange?: (params: GenericTableParams) => void }, - ResultProps extends { _id?: Key }, - >( - props: GenericTableProps & RefAttributes, - ): ReactElement | null; -} = forwardRef(function GenericTable( +const GenericTable = forwardRef(function GenericTable< + FilterProps extends { onChange?: (params: GenericTableParams) => void }, + ResultProps extends { _id?: Key }, +>( { children, fixed = true, @@ -57,41 +56,29 @@ const GenericTable: { total, pagination = true, ...props - }, - ref, + }: GenericTableProps, + ref: Ref, ) { const t = useTranslation(); const [filter, setFilter] = useState(paramsDefault); - const [itemsPerPage, setItemsPerPage] = useState<25 | 50 | 100>(25); - - const [current, setCurrent] = useState(0); + const { + itemsPerPage, + setItemsPerPage, + current, + setCurrent, + itemsPerPageLabel, + showingResultsLabel, + } = usePagination(); const params = useDebouncedValue(filter, 500); useEffect(() => { - setParams({ ...params, current, itemsPerPage }); + setParams({ text: params.text || '', current, itemsPerPage }); }, [params, current, itemsPerPage, setParams]); - const Loading = useCallback(() => { - const headerCells = flattenChildren(header); - return ( - <> - {Array.from({ length: 10 }, (_, i) => ( - - ))} - - ); - }, [header]); - - const showingResultsLabel = useCallback( - ({ count, current, itemsPerPage }) => - t('Showing_results_of', current + 1, Math.min(current + itemsPerPage, count), count), - [t], - ); - - const itemsPerPageLabel = useCallback(() => t('Items_per_page:'), [t]); + const headerCells = useMemo(() => flattenChildren(header).length, [header]); return ( <> @@ -104,28 +91,18 @@ const GenericTable: { ) : ( <> - - - - {header && ( - - {header} - - )} - - {RenderRow && - (results ? ( - results.map((props, index) => ( - - )) - ) : ( - - ))} - {children && (results ? results.map(children) : )} - -
-
-
+ + {header && {header}} + + {!results && } + {!!results && + ((RenderRow && + results.map((props, index: number) => ( + + ))) || + (children && results.map(children)))} + + {pagination && ( (function GenericTable( + { fixed = true, children }, + ref, +) { + return ( + + + + {children} +
+
+
+ ); +}); diff --git a/client/components/GenericTable/V2/GenericTableBody.tsx b/client/components/GenericTable/V2/GenericTableBody.tsx new file mode 100644 index 0000000000000..40f5a72a91902 --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableBody.tsx @@ -0,0 +1,4 @@ +import { Table } from '@rocket.chat/fuselage'; +import React, { FC } from 'react'; + +export const GenericTableBody: FC = ({ children }) => {children}; diff --git a/client/components/GenericTable/V2/GenericTableCell.tsx b/client/components/GenericTable/V2/GenericTableCell.tsx new file mode 100644 index 0000000000000..f5372be685352 --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableCell.tsx @@ -0,0 +1,6 @@ +import { Table } from '@rocket.chat/fuselage'; +import React, { ComponentProps, FC } from 'react'; + +export const GenericTableCell: FC> = ({ children }) => ( + {children} +); diff --git a/client/components/GenericTable/V2/GenericTableHeader.tsx b/client/components/GenericTable/V2/GenericTableHeader.tsx new file mode 100644 index 0000000000000..9b5613b928b6e --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableHeader.tsx @@ -0,0 +1,10 @@ +import { Table } from '@rocket.chat/fuselage'; +import React, { FC } from 'react'; + +import { GenericTableRow } from './GenericTableRow'; + +export const GenericTableHeader: FC = ({ children }) => ( + + {children} + +); diff --git a/client/components/GenericTable/V2/GenericTableHeaderCell.tsx b/client/components/GenericTable/V2/GenericTableHeaderCell.tsx new file mode 100644 index 0000000000000..a4db4fbb31600 --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableHeaderCell.tsx @@ -0,0 +1,30 @@ +import { Box, Table } from '@rocket.chat/fuselage'; +import React, { ComponentProps, ReactElement, useCallback } from 'react'; + +import SortIcon from '../SortIcon'; + +type GenericTableHeaderCellProps = Omit, 'onClick'> & { + active?: boolean; + direction?: 'asc' | 'desc'; + sort?: T; + onClick?: (sort: T) => void; +}; + +export const GenericTableHeaderCell = ({ + children, + active, + direction, + sort, + onClick, + ...props +}: GenericTableHeaderCellProps): ReactElement => { + const fn = useCallback(() => onClick && sort && onClick(sort), [sort, onClick]); + return ( + + + {children} + {sort && } + + + ); +}; diff --git a/client/components/GenericTable/V2/GenericTableLoadingRow.tsx b/client/components/GenericTable/V2/GenericTableLoadingRow.tsx new file mode 100644 index 0000000000000..fa58836e86e79 --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableLoadingRow.tsx @@ -0,0 +1,25 @@ +import { Box, Skeleton, Table } from '@rocket.chat/fuselage'; +import React, { FC } from 'react'; + +type GenericTableLoadingRowRowProps = { + cols: number; +}; + +export const GenericTableLoadingRow: FC = ({ cols }) => ( + + + + + + + + + + + {Array.from({ length: cols - 1 }, (_, i) => ( + + + + ))} + +); diff --git a/client/components/GenericTable/V2/GenericTableLoadingTable.tsx b/client/components/GenericTable/V2/GenericTableLoadingTable.tsx new file mode 100644 index 0000000000000..e7f2501bc7f4d --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableLoadingTable.tsx @@ -0,0 +1,15 @@ +import React, { ReactElement } from 'react'; + +import { GenericTableLoadingRow } from './GenericTableLoadingRow'; + +export const GenericTableLoadingTable = ({ + headerCells, +}: { + headerCells: number; +}): ReactElement => ( + <> + {Array.from({ length: 10 }, (_, i) => ( + + ))} + +); diff --git a/client/components/GenericTable/V2/GenericTableRow.tsx b/client/components/GenericTable/V2/GenericTableRow.tsx new file mode 100644 index 0000000000000..86b23eac18428 --- /dev/null +++ b/client/components/GenericTable/V2/GenericTableRow.tsx @@ -0,0 +1,6 @@ +import { Table } from '@rocket.chat/fuselage'; +import React, { ComponentProps, FC } from 'react'; + +export const GenericTableRow: FC> = ({ children }) => ( + {children} +); diff --git a/client/components/GenericTable/hooks/useCurrent.ts b/client/components/GenericTable/hooks/useCurrent.ts new file mode 100644 index 0000000000000..fc70a9f252d20 --- /dev/null +++ b/client/components/GenericTable/hooks/useCurrent.ts @@ -0,0 +1,9 @@ +import { useState } from 'react'; + +export const useCurrent = ( + currentInitialValue = 0, +): [number, React.Dispatch>] => { + const [current, setCurrent] = useState(currentInitialValue); + + return [current, setCurrent]; +}; diff --git a/client/components/GenericTable/hooks/useItemsPerPage.ts b/client/components/GenericTable/hooks/useItemsPerPage.ts new file mode 100644 index 0000000000000..3d9c36807a61e --- /dev/null +++ b/client/components/GenericTable/hooks/useItemsPerPage.ts @@ -0,0 +1,11 @@ +import { useState } from 'react'; + +type UseItemsPerPageValue = 25 | 50 | 100; + +export const useItemsPerPage = ( + itemsPerPageInitialValue: UseItemsPerPageValue = 25, +): [UseItemsPerPageValue, React.Dispatch>] => { + const [itemsPerPage, setItemsPerPage] = useState(itemsPerPageInitialValue); + + return [itemsPerPage, setItemsPerPage]; +}; diff --git a/client/components/GenericTable/hooks/useItemsPerPageLabel.ts b/client/components/GenericTable/hooks/useItemsPerPageLabel.ts new file mode 100644 index 0000000000000..79e65d88f3702 --- /dev/null +++ b/client/components/GenericTable/hooks/useItemsPerPageLabel.ts @@ -0,0 +1,8 @@ +import { useCallback } from 'react'; + +import { useTranslation } from '../../../contexts/TranslationContext'; + +export const useItemsPerPageLabel = (): (() => string) => { + const t = useTranslation(); + return useCallback(() => t('Items_per_page:'), [t]); +}; diff --git a/client/components/GenericTable/hooks/usePagination.ts b/client/components/GenericTable/hooks/usePagination.ts new file mode 100644 index 0000000000000..5f088cc06d9c6 --- /dev/null +++ b/client/components/GenericTable/hooks/usePagination.ts @@ -0,0 +1,30 @@ +import { useCurrent } from './useCurrent'; +import { useItemsPerPage } from './useItemsPerPage'; +import { useItemsPerPageLabel } from './useItemsPerPageLabel'; +import { useShowingResultsLabel } from './useShowingResultsLabel'; + +export const usePagination = (): { + current: ReturnType[0]; + setCurrent: ReturnType[1]; + itemsPerPage: ReturnType[0]; + setItemsPerPage: ReturnType[1]; + itemsPerPageLabel: ReturnType; + showingResultsLabel: ReturnType; +} => { + const [itemsPerPage, setItemsPerPage] = useItemsPerPage(); + + const [current, setCurrent] = useCurrent(); + + const itemsPerPageLabel = useItemsPerPageLabel(); + + const showingResultsLabel = useItemsPerPageLabel(); + + return { + itemsPerPage, + setItemsPerPage, + current, + setCurrent, + itemsPerPageLabel, + showingResultsLabel, + }; +}; diff --git a/client/components/GenericTable/hooks/useShowingResultsLabel.ts b/client/components/GenericTable/hooks/useShowingResultsLabel.ts new file mode 100644 index 0000000000000..b7a54ac084f90 --- /dev/null +++ b/client/components/GenericTable/hooks/useShowingResultsLabel.ts @@ -0,0 +1,19 @@ +import { Pagination } from '@rocket.chat/fuselage'; +import { ComponentProps, useCallback } from 'react'; + +import { useTranslation } from '../../../contexts/TranslationContext'; + +type Props< + T extends ComponentProps['showingResultsLabel'] = ComponentProps< + typeof Pagination + >['showingResultsLabel'], +> = T extends (...args: any[]) => any ? Parameters : never; + +export const useShowingResultsLabel = (): ((...params: Props) => string) => { + const t = useTranslation(); + return useCallback( + ({ count, current, itemsPerPage }) => + t('Showing_results_of', current + 1, Math.min(current + itemsPerPage, count), count), + [t], + ); +}; diff --git a/client/components/GenericTable/hooks/useSort.ts b/client/components/GenericTable/hooks/useSort.ts new file mode 100644 index 0000000000000..6858404208fcd --- /dev/null +++ b/client/components/GenericTable/hooks/useSort.ts @@ -0,0 +1,34 @@ +import { useCallback, useState } from 'react'; + +type Direction = 'asc' | 'desc'; + +export const useSort = ( + by: T, + initialDirection: Direction = 'asc', +): { + sortBy: T; + sortDirection: Direction; + setSort: (sortBy: T, direction?: Direction | undefined) => void; +} => { + const [sort, _setSort] = useState<[T, Direction]>(() => [by, initialDirection]); + + const setSort = useCallback((id: T, direction?: Direction | undefined) => { + _setSort(([sortBy, sortDirection]) => { + if (direction) { + return [id, direction]; + } + + if (sortBy === id) { + return [id, sortDirection === 'asc' ? 'desc' : 'asc']; + } + + return [id, 'asc']; + }); + }, []); + + return { + sortBy: sort[0], + sortDirection: sort[1], + setSort, + }; +}; diff --git a/client/components/GenericTable/index.ts b/client/components/GenericTable/index.ts index 8da6df3fc14e1..3a51504430245 100644 --- a/client/components/GenericTable/index.ts +++ b/client/components/GenericTable/index.ts @@ -4,3 +4,12 @@ import HeaderCell from './HeaderCell'; export default Object.assign(GenericTable, { HeaderCell, }); + +export * from './V2/GenericTable'; +export * from './V2/GenericTableBody'; +export * from './V2/GenericTableCell'; +export * from './V2/GenericTableHeader'; +export * from './V2/GenericTableHeaderCell'; +export * from './V2/GenericTableLoadingRow'; +export * from './V2/GenericTableLoadingTable'; +export * from './V2/GenericTableRow'; diff --git a/client/views/admin/customEmoji/CustomEmoji.js b/client/views/admin/customEmoji/CustomEmoji.js deleted file mode 100644 index b5474ab6d3ef1..0000000000000 --- a/client/views/admin/customEmoji/CustomEmoji.js +++ /dev/null @@ -1,65 +0,0 @@ -import { Box, Table } from '@rocket.chat/fuselage'; -import React, { useMemo } from 'react'; - -import FilterByText from '../../../components/FilterByText'; -import GenericTable from '../../../components/GenericTable'; -import { useTranslation } from '../../../contexts/TranslationContext'; - -function CustomEmoji({ data, sort, onClick, onHeaderClick, setParams, params }) { - const t = useTranslation(); - - const header = useMemo( - () => [ - - {t('Name')} - , - - {t('Aliases')} - , - ], - [onHeaderClick, sort, t], - ); - - const renderRow = (emojis) => { - const { _id, name, aliases } = emojis; - return ( - - - {name} - - - {aliases} - - - ); - }; - - return ( - } - /> - ); -} - -export default CustomEmoji; diff --git a/client/views/admin/customEmoji/CustomEmoji.tsx b/client/views/admin/customEmoji/CustomEmoji.tsx new file mode 100644 index 0000000000000..384a4a7240f77 --- /dev/null +++ b/client/views/admin/customEmoji/CustomEmoji.tsx @@ -0,0 +1,119 @@ +import { Box, Pagination } from '@rocket.chat/fuselage'; +import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; +import React, { FC, MutableRefObject, useEffect, useMemo, useState } from 'react'; + +import FilterByText from '../../../components/FilterByText'; +import { + GenericTable, + GenericTableBody, + GenericTableCell, + GenericTableHeader, + GenericTableHeaderCell, + GenericTableLoadingTable, + GenericTableRow, +} from '../../../components/GenericTable'; +import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; +import { useSort } from '../../../components/GenericTable/hooks/useSort'; +import { useTranslation } from '../../../contexts/TranslationContext'; +import { useEndpointData } from '../../../hooks/useEndpointData'; +import { AsyncStatePhase } from '../../../lib/asyncState'; + +type CustomEmojiProps = { + reload: MutableRefObject<() => void>; + onClick: (emoji: string) => () => void; +}; + +const CustomEmoji: FC = function CustomEmoji({ onClick, reload }) { + const t = useTranslation(); + + const { + current, + itemsPerPage, + setItemsPerPage: onSetItemsPerPage, + setCurrent: onSetCurrent, + ...paginationProps + } = usePagination(); + + const [text, setText] = useState(''); + + const { sortBy, sortDirection, setSort } = useSort<'name'>('name'); + + const query = useDebouncedValue( + useMemo( + () => ({ + query: JSON.stringify({ name: { $regex: text || '', $options: 'i' } }), + sort: JSON.stringify({ [sortBy]: sortDirection === 'asc' ? 1 : -1 }), + ...(itemsPerPage && { count: itemsPerPage }), + ...(current && { offset: current }), + }), + [text, itemsPerPage, current, sortBy, sortDirection], + ), + 500, + ); + + const { value: data, phase, reload: reloadEndPoint } = useEndpointData('emoji-custom.all', query); + + useEffect(() => { + reload.current = reloadEndPoint; + }, [reload, reloadEndPoint]); + return ( + <> + setText(text)} /> + + + + {t('Name')} + + + {t('Aliases')} + + + + {phase === AsyncStatePhase.LOADING && } + {phase === AsyncStatePhase.RESOLVED && + data.emojis.length > 0 && + data.emojis.map((emojis) => ( + + + {emojis.name} + + + {emojis.aliases} + + + ))} + {/* {phase === AsyncStatePhase.RESOLVED && + !data.emojis.length + ))} */} + + + {phase === AsyncStatePhase.RESOLVED && ( + + )} + + ); +}; + +export default CustomEmoji; diff --git a/client/views/admin/customEmoji/CustomEmojiRoute.js b/client/views/admin/customEmoji/CustomEmojiRoute.js index d1430d21062a5..36cb32d84a62e 100644 --- a/client/views/admin/customEmoji/CustomEmojiRoute.js +++ b/client/views/admin/customEmoji/CustomEmojiRoute.js @@ -1,6 +1,5 @@ import { Button, Icon } from '@rocket.chat/fuselage'; -import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import React, { useMemo, useState, useCallback } from 'react'; +import React, { useCallback, useRef } from 'react'; import NotAuthorizedPage from '../../../components/NotAuthorizedPage'; import Page from '../../../components/Page'; @@ -8,7 +7,6 @@ import VerticalBar from '../../../components/VerticalBar'; import { usePermission } from '../../../contexts/AuthorizationContext'; import { useRoute, useRouteParameter } from '../../../contexts/RouterContext'; import { useTranslation } from '../../../contexts/TranslationContext'; -import { useEndpointData } from '../../../hooks/useEndpointData'; import AddCustomEmoji from './AddCustomEmoji'; import CustomEmoji from './CustomEmoji'; import EditCustomEmojiWithData from './EditCustomEmojiWithData'; @@ -20,24 +18,6 @@ function CustomEmojiRoute() { const canManageEmoji = usePermission('manage-emoji'); const t = useTranslation(); - - const [params, setParams] = useState(() => ({ text: '', current: 0, itemsPerPage: 25 })); - const [sort, setSort] = useState(() => ['name', 'asc']); - - const { text, itemsPerPage, current } = useDebouncedValue(params, 500); - const [column, direction] = useDebouncedValue(sort, 500); - const query = useMemo( - () => ({ - query: JSON.stringify({ name: { $regex: text || '', $options: 'i' } }), - sort: JSON.stringify({ [column]: direction === 'asc' ? 1 : -1 }), - ...(itemsPerPage && { count: itemsPerPage }), - ...(current && { offset: current }), - }), - [text, itemsPerPage, current, column, direction], - ); - - const { value: data, reload } = useEndpointData('emoji-custom.all', query); - const handleItemClick = (_id) => () => { route.push({ context: 'edit', @@ -45,16 +25,6 @@ function CustomEmojiRoute() { }); }; - const handleHeaderClick = (id) => { - setSort(([sortBy, sortDirection]) => { - if (sortBy === id) { - return [id, sortDirection === 'asc' ? 'desc' : 'asc']; - } - - return [id, 'asc']; - }); - }; - const handleNewButtonClick = useCallback(() => { route.push({ context: 'new' }); }, [route]); @@ -63,8 +33,10 @@ function CustomEmojiRoute() { route.push({}); }; + const reload = useRef(() => null); + const handleChange = useCallback(() => { - reload(); + reload.current(); }, [reload]); if (!canManageEmoji) { @@ -80,14 +52,7 @@ function CustomEmojiRoute() { - + {context && ( diff --git a/definition/rest/v1/emojiCustom.ts b/definition/rest/v1/emojiCustom.ts index 0a49286ecfd53..c2c4a0162f3cf 100644 --- a/definition/rest/v1/emojiCustom.ts +++ b/definition/rest/v1/emojiCustom.ts @@ -1,14 +1,26 @@ -import type { ICustomEmojiDescriptor } from '../../ICustomEmojiDescriptor'; +import type { ICustomEmojiDescriptor } from "../../ICustomEmojiDescriptor"; +import { Serialized } from "../../Serialized"; +import { PaginatedRequest } from "../helpers/PaginatedRequest"; +import { PaginatedResult } from "../helpers/PaginatedResult"; export type EmojiCustomEndpoints = { - 'emoji-custom.list': { - GET: (params: { query: string }) => { - emojis?: { - update: ICustomEmojiDescriptor[]; - }; - }; - }; - 'emoji-custom.delete': { - POST: (params: { emojiId: ICustomEmojiDescriptor['_id'] }) => void; - }; + "emoji-custom.all": { + GET: ( + params: { query: string } & PaginatedRequest & { + sort: string; //{name: "asc" | "desc";}>; + } + ) => { + emojis: ICustomEmojiDescriptor[]; + } & PaginatedResult; + }; + "emoji-custom.list": { + GET: (params: { query: string }) => { + emojis?: { + update: ICustomEmojiDescriptor[]; + }; + }; + }; + "emoji-custom.delete": { + POST: (params: { emojiId: ICustomEmojiDescriptor["_id"] }) => void; + }; }; From 92afd6d4092c338687138b3ad58e82b95414b38c Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 18 Nov 2021 09:06:59 -0300 Subject: [PATCH 2/4] lint --- .../GenericTable/V2/GenericTableBody.tsx | 2 +- .../GenericTable/V2/GenericTableCell.tsx | 4 +- .../GenericTable/V2/GenericTableHeader.tsx | 4 +- .../GenericTable/V2/GenericTableRow.tsx | 4 +- .../views/admin/customEmoji/CustomEmoji.tsx | 10 +++-- definition/rest/v1/emojiCustom.ts | 45 +++++++++---------- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/client/components/GenericTable/V2/GenericTableBody.tsx b/client/components/GenericTable/V2/GenericTableBody.tsx index 40f5a72a91902..945688f9efafe 100644 --- a/client/components/GenericTable/V2/GenericTableBody.tsx +++ b/client/components/GenericTable/V2/GenericTableBody.tsx @@ -1,4 +1,4 @@ import { Table } from '@rocket.chat/fuselage'; import React, { FC } from 'react'; -export const GenericTableBody: FC = ({ children }) => {children}; +export const GenericTableBody: FC = (props) => ; diff --git a/client/components/GenericTable/V2/GenericTableCell.tsx b/client/components/GenericTable/V2/GenericTableCell.tsx index f5372be685352..883de10b3f3ad 100644 --- a/client/components/GenericTable/V2/GenericTableCell.tsx +++ b/client/components/GenericTable/V2/GenericTableCell.tsx @@ -1,6 +1,6 @@ import { Table } from '@rocket.chat/fuselage'; import React, { ComponentProps, FC } from 'react'; -export const GenericTableCell: FC> = ({ children }) => ( - {children} +export const GenericTableCell: FC> = (props) => ( + ); diff --git a/client/components/GenericTable/V2/GenericTableHeader.tsx b/client/components/GenericTable/V2/GenericTableHeader.tsx index 9b5613b928b6e..90f3a340f5a1e 100644 --- a/client/components/GenericTable/V2/GenericTableHeader.tsx +++ b/client/components/GenericTable/V2/GenericTableHeader.tsx @@ -3,8 +3,8 @@ import React, { FC } from 'react'; import { GenericTableRow } from './GenericTableRow'; -export const GenericTableHeader: FC = ({ children }) => ( - +export const GenericTableHeader: FC = ({ children, ...props }) => ( + {children} ); diff --git a/client/components/GenericTable/V2/GenericTableRow.tsx b/client/components/GenericTable/V2/GenericTableRow.tsx index 86b23eac18428..cd31eb47d65c9 100644 --- a/client/components/GenericTable/V2/GenericTableRow.tsx +++ b/client/components/GenericTable/V2/GenericTableRow.tsx @@ -1,6 +1,6 @@ import { Table } from '@rocket.chat/fuselage'; import React, { ComponentProps, FC } from 'react'; -export const GenericTableRow: FC> = ({ children }) => ( - {children} +export const GenericTableRow: FC> = (props) => ( + ); diff --git a/client/views/admin/customEmoji/CustomEmoji.tsx b/client/views/admin/customEmoji/CustomEmoji.tsx index 384a4a7240f77..c4799c2de45bd 100644 --- a/client/views/admin/customEmoji/CustomEmoji.tsx +++ b/client/views/admin/customEmoji/CustomEmoji.tsx @@ -43,8 +43,8 @@ const CustomEmoji: FC = function CustomEmoji({ onClick, reload () => ({ query: JSON.stringify({ name: { $regex: text || '', $options: 'i' } }), sort: JSON.stringify({ [sortBy]: sortDirection === 'asc' ? 1 : -1 }), - ...(itemsPerPage && { count: itemsPerPage }), - ...(current && { offset: current }), + count: itemsPerPage, + offset: current, }), [text, itemsPerPage, current, sortBy, sortDirection], ), @@ -78,8 +78,10 @@ const CustomEmoji: FC = function CustomEmoji({ onClick, reload {phase === AsyncStatePhase.LOADING && } {phase === AsyncStatePhase.RESOLVED && + data && + data.emojis && data.emojis.length > 0 && - data.emojis.map((emojis) => ( + data?.emojis.map((emojis) => ( = function CustomEmoji({ onClick, reload ; - } - ) => { - emojis: ICustomEmojiDescriptor[]; - } & PaginatedResult; - }; - "emoji-custom.list": { - GET: (params: { query: string }) => { - emojis?: { - update: ICustomEmojiDescriptor[]; - }; - }; - }; - "emoji-custom.delete": { - POST: (params: { emojiId: ICustomEmojiDescriptor["_id"] }) => void; - }; + 'emoji-custom.all': { + GET: ( + params: { query: string } & PaginatedRequest & { + sort: string; // {name: 'asc' | 'desc';}>; + } + ) => { + emojis: ICustomEmojiDescriptor[]; + } & PaginatedResult; + }; + 'emoji-custom.list': { + GET: (params: { query: string }) => { + emojis?: { + update: ICustomEmojiDescriptor[]; + }; + }; + }; + 'emoji-custom.delete': { + POST: (params: { emojiId: ICustomEmojiDescriptor['_id'] }) => void; + }; }; From 7135b6347c8a5223071605c3bc2d3dd9e88f990c Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 18 Nov 2021 11:51:26 -0300 Subject: [PATCH 3/4] Fix review --- client/components/GenericTable/GenericTable.tsx | 10 ++++++---- client/components/GenericTable/V2/GenericTable.tsx | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/client/components/GenericTable/GenericTable.tsx b/client/components/GenericTable/GenericTable.tsx index a345475107519..c6e5317d24ed4 100644 --- a/client/components/GenericTable/GenericTable.tsx +++ b/client/components/GenericTable/GenericTable.tsx @@ -80,6 +80,8 @@ const GenericTable = forwardRef(function GenericTable< const headerCells = useMemo(() => flattenChildren(header).length, [header]); + const isLoading = !results; + return ( <> {typeof renderFilter === 'function' @@ -94,13 +96,13 @@ const GenericTable = forwardRef(function GenericTable< {header && {header}} - {!results && } - {!!results && + {isLoading && } + {!isLoading && ((RenderRow && - results.map((props, index: number) => ( + results?.map((props, index: number) => ( ))) || - (children && results.map(children)))} + (children && results?.map(children)))} {pagination && ( diff --git a/client/components/GenericTable/V2/GenericTable.tsx b/client/components/GenericTable/V2/GenericTable.tsx index 6b1dbcb8c982e..33b23a5f2dead 100644 --- a/client/components/GenericTable/V2/GenericTable.tsx +++ b/client/components/GenericTable/V2/GenericTable.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-multi-comp */ import { Box, Table } from '@rocket.chat/fuselage'; import React, { forwardRef, ReactNode } from 'react'; From 253422219bf0a05a656dc228964d0270db54092a Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 18 Nov 2021 17:37:00 -0300 Subject: [PATCH 4/4] Fix Gb review --- client/components/GenericTable/V2/GenericTableLoadingRow.tsx | 4 ++-- client/components/GenericTable/hooks/usePagination.ts | 2 +- client/views/admin/customEmoji/CustomEmoji.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/components/GenericTable/V2/GenericTableLoadingRow.tsx b/client/components/GenericTable/V2/GenericTableLoadingRow.tsx index fa58836e86e79..ecc34e2e5e7f3 100644 --- a/client/components/GenericTable/V2/GenericTableLoadingRow.tsx +++ b/client/components/GenericTable/V2/GenericTableLoadingRow.tsx @@ -1,11 +1,11 @@ import { Box, Skeleton, Table } from '@rocket.chat/fuselage'; -import React, { FC } from 'react'; +import React, { ReactElement } from 'react'; type GenericTableLoadingRowRowProps = { cols: number; }; -export const GenericTableLoadingRow: FC = ({ cols }) => ( +export const GenericTableLoadingRow = ({ cols }: GenericTableLoadingRowRowProps): ReactElement => ( diff --git a/client/components/GenericTable/hooks/usePagination.ts b/client/components/GenericTable/hooks/usePagination.ts index 5f088cc06d9c6..3f0558f4ac995 100644 --- a/client/components/GenericTable/hooks/usePagination.ts +++ b/client/components/GenericTable/hooks/usePagination.ts @@ -17,7 +17,7 @@ export const usePagination = (): { const itemsPerPageLabel = useItemsPerPageLabel(); - const showingResultsLabel = useItemsPerPageLabel(); + const showingResultsLabel = useShowingResultsLabel(); return { itemsPerPage, diff --git a/client/views/admin/customEmoji/CustomEmoji.tsx b/client/views/admin/customEmoji/CustomEmoji.tsx index c4799c2de45bd..28db8f4b4cec9 100644 --- a/client/views/admin/customEmoji/CustomEmoji.tsx +++ b/client/views/admin/customEmoji/CustomEmoji.tsx @@ -108,7 +108,7 @@ const CustomEmoji: FC = function CustomEmoji({ onClick, reload