import React from 'react'; import { useHistory } from 'react-router'; import { TopicWithDetailedInfo, ClusterName, TopicName, } from 'redux/interfaces'; import { useParams } from 'react-router-dom'; import { clusterTopicCopyPath, clusterTopicNewPath } from 'lib/paths'; import usePagination from 'lib/hooks/usePagination'; import ClusterContext from 'components/contexts/ClusterContext'; import PageLoader from 'components/common/PageLoader/PageLoader'; import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal'; import { CleanUpPolicy, GetTopicsRequest, SortOrder, TopicColumnsToSort, } from 'generated-sources'; import Search from 'components/common/Search/Search'; import { PER_PAGE } from 'lib/constants'; import { Button } from 'components/common/Button/Button'; import PageHeading from 'components/common/PageHeading/PageHeading'; import { ControlPanelWrapper } from 'components/common/ControlPanel/ControlPanel.styled'; import Switch from 'components/common/Switch/Switch'; import { SmartTable } from 'components/common/SmartTable/SmartTable'; import { TableCellProps, TableColumn, } from 'components/common/SmartTable/TableColumn'; import { useTableState } from 'lib/hooks/useTableState'; import Dropdown from 'components/common/Dropdown/Dropdown'; import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon'; import DropdownItem from 'components/common/Dropdown/DropdownItem'; import { MessagesCell, OutOfSyncReplicasCell, TitleCell, TopicSizeCell, } from './TopicsTableCells'; import { ActionsTd } from './List.styled'; export interface TopicsListProps { areTopicsFetching: boolean; topics: TopicWithDetailedInfo[]; totalPages: number; fetchTopicsList(props: GetTopicsRequest): void; deleteTopic(topicName: TopicName, clusterName: ClusterName): void; deleteTopics(topicName: TopicName, clusterNames: ClusterName[]): void; recreateTopic(topicName: TopicName, clusterName: ClusterName): void; clearTopicsMessages(topicName: TopicName, clusterNames: ClusterName[]): void; clearTopicMessages( topicName: TopicName, clusterName: ClusterName, partitions?: number[] ): void; search: string; orderBy: TopicColumnsToSort | null; sortOrder: SortOrder; setTopicsSearch(search: string): void; setTopicsOrderBy(orderBy: TopicColumnsToSort | null): void; } const List: React.FC = ({ areTopicsFetching, topics, totalPages, fetchTopicsList, deleteTopic, deleteTopics, recreateTopic, clearTopicMessages, clearTopicsMessages, search, orderBy, sortOrder, setTopicsSearch, setTopicsOrderBy, }) => { const { isReadOnly, isTopicDeletionAllowed } = React.useContext(ClusterContext); const { clusterName } = useParams<{ clusterName: ClusterName }>(); const { page, perPage, pathname } = usePagination(); const [showInternal, setShowInternal] = React.useState( !localStorage.getItem('hideInternalTopics') && true ); const [cachedPage, setCachedPage] = React.useState(null); const history = useHistory(); React.useEffect(() => { fetchTopicsList({ clusterName, page, perPage, orderBy: orderBy || undefined, sortOrder, search, showInternal, }); }, [ fetchTopicsList, clusterName, page, perPage, orderBy, sortOrder, search, showInternal, ]); const tableState = useTableState< TopicWithDetailedInfo, string, TopicColumnsToSort >( topics, { idSelector: (topic) => topic.name, totalPages, isRowSelectable: (topic) => !topic.internal, }, { handleOrderBy: setTopicsOrderBy, orderBy, sortOrder, } ); const getSelectedTopic = (): string => { const name = Array.from(tableState.selectedIds)[0]; const selectedTopic = tableState.data.find( (topic: TopicWithDetailedInfo) => topic.name === name ) || {}; return Object.keys(selectedTopic) .map((x: string) => { const value = selectedTopic[x as keyof typeof selectedTopic]; return value && x !== 'partitions' ? `${x}=${value}` : null; }) .join('&'); }; const handleSwitch = React.useCallback(() => { if (showInternal) { localStorage.setItem('hideInternalTopics', 'true'); } else { localStorage.removeItem('hideInternalTopics'); } setShowInternal(!showInternal); history.push(`${pathname}?page=1&perPage=${perPage || PER_PAGE}`); }, [history, pathname, perPage, showInternal]); const [confirmationModal, setConfirmationModal] = React.useState< '' | 'deleteTopics' | 'purgeMessages' >(''); const [confirmationModalText, setConfirmationModalText] = React.useState(''); const closeConfirmationModal = () => { setConfirmationModal(''); }; const clearSelectedTopics = React.useCallback(() => { tableState.toggleSelection(false); }, [tableState]); const searchHandler = React.useCallback( (searchString: string) => { setTopicsSearch(searchString); setCachedPage(page || null); const newPageQuery = !searchString && cachedPage ? cachedPage : 1; history.push( `${pathname}?page=${newPageQuery}&perPage=${perPage || PER_PAGE}` ); }, [setTopicsSearch, history, pathname, perPage, page] ); const deleteOrPurgeConfirmationHandler = React.useCallback(() => { const selectedIds = Array.from(tableState.selectedIds); if (confirmationModal === 'deleteTopics') { deleteTopics(clusterName, selectedIds); } else { clearTopicsMessages(clusterName, selectedIds); } closeConfirmationModal(); clearSelectedTopics(); }, [ confirmationModal, clearSelectedTopics, clusterName, deleteTopics, clearTopicsMessages, tableState.selectedIds, ]); const ActionsCell = React.memo>( ({ hovered, dataItem: { internal, cleanUpPolicy, name } }) => { const [ isDeleteTopicConfirmationVisible, setDeleteTopicConfirmationVisible, ] = React.useState(false); const [ isRecreateTopicConfirmationVisible, setRecreateTopicConfirmationVisible, ] = React.useState(false); const isHidden = internal || isReadOnly || !hovered; const deleteTopicHandler = React.useCallback(() => { deleteTopic(clusterName, name); }, [name]); const clearTopicMessagesHandler = React.useCallback(() => { clearTopicMessages(clusterName, name); }, [name]); const recreateTopicHandler = React.useCallback(() => { recreateTopic(clusterName, name); setRecreateTopicConfirmationVisible(false); }, [name]); return ( <>
{!isHidden && ( } right> {cleanUpPolicy === CleanUpPolicy.DELETE && ( Clear Messages )} {isTopicDeletionAllowed && ( setDeleteTopicConfirmationVisible(true)} danger > Remove Topic )} setRecreateTopicConfirmationVisible(true)} danger > Recreate Topic )}
setDeleteTopicConfirmationVisible(false)} onConfirm={deleteTopicHandler} > Are you sure want to remove {name} topic? setRecreateTopicConfirmationVisible(false)} onConfirm={recreateTopicHandler} > Are you sure to recreate {name} topic? ); } ); return (
{!isReadOnly && ( )}
{areTopicsFetching ? ( ) : (
{tableState.selectedCount > 0 && ( <> {tableState.selectedCount === 1 && ( )} {confirmationModalText} )}
)}
); }; export default List;