import React, { useCallback, useMemo, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { IndexerAppState } from 'App/State/SettingsAppState'; import Alert from 'Components/Alert'; import Button from 'Components/Link/Button'; import SpinnerButton from 'Components/Link/SpinnerButton'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import ConfirmModal from 'Components/Modal/ConfirmModal'; import ModalBody from 'Components/Modal/ModalBody'; import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; import useSelectState from 'Helpers/Hooks/useSelectState'; import { kinds } from 'Helpers/Props'; import SortDirection from 'Helpers/Props/SortDirection'; import { bulkDeleteIndexers, bulkEditIndexers, setManageIndexersSort, } from 'Store/Actions/settingsActions'; import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; import { SelectStateInputProps } from 'typings/props'; import getErrorMessage from 'Utilities/Object/getErrorMessage'; import translate from 'Utilities/String/translate'; import getSelectedIds from 'Utilities/Table/getSelectedIds'; import ManageIndexersEditModal from './Edit/ManageIndexersEditModal'; import ManageIndexersModalRow from './ManageIndexersModalRow'; import TagsModal from './Tags/TagsModal'; import styles from './ManageIndexersModalContent.css'; // TODO: This feels janky to do, but not sure of a better way currently type OnSelectedChangeCallback = React.ComponentProps< typeof ManageIndexersModalRow >['onSelectedChange']; const COLUMNS = [ { name: 'name', label: () => translate('Name'), isSortable: true, isVisible: true, }, { name: 'implementation', label: () => translate('Implementation'), isSortable: true, isVisible: true, }, { name: 'enableRss', label: () => translate('EnableRSS'), isSortable: true, isVisible: true, }, { name: 'enableAutomaticSearch', label: () => translate('EnableAutomaticSearch'), isSortable: true, isVisible: true, }, { name: 'enableInteractiveSearch', label: () => translate('EnableInteractiveSearch'), isSortable: true, isVisible: true, }, { name: 'priority', label: () => translate('Priority'), isSortable: true, isVisible: true, }, { name: 'tags', label: () => translate('Tags'), isSortable: true, isVisible: true, }, ]; interface ManageIndexersModalContentProps { onModalClose(): void; sortKey?: string; sortDirection?: SortDirection; } function ManageIndexersModalContent(props: ManageIndexersModalContentProps) { const { onModalClose } = props; const { isFetching, isPopulated, isDeleting, isSaving, error, items, sortKey, sortDirection, }: IndexerAppState = useSelector( createClientSideCollectionSelector('settings.indexers') ); const dispatch = useDispatch(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isTagsModalOpen, setIsTagsModalOpen] = useState(false); const [isSavingTags, setIsSavingTags] = useState(false); const [selectState, setSelectState] = useSelectState(); const { allSelected, allUnselected, selectedState } = selectState; const selectedIds: number[] = useMemo(() => { return getSelectedIds(selectedState); }, [selectedState]); const selectedCount = selectedIds.length; const onSortPress = useCallback( (value: string) => { dispatch(setManageIndexersSort({ sortKey: value })); }, [dispatch] ); const onDeletePress = useCallback(() => { setIsDeleteModalOpen(true); }, [setIsDeleteModalOpen]); const onDeleteModalClose = useCallback(() => { setIsDeleteModalOpen(false); }, [setIsDeleteModalOpen]); const onEditPress = useCallback(() => { setIsEditModalOpen(true); }, [setIsEditModalOpen]); const onEditModalClose = useCallback(() => { setIsEditModalOpen(false); }, [setIsEditModalOpen]); const onConfirmDelete = useCallback(() => { dispatch(bulkDeleteIndexers({ ids: selectedIds })); setIsDeleteModalOpen(false); }, [selectedIds, dispatch]); const onSavePress = useCallback( (payload: object) => { setIsEditModalOpen(false); dispatch( bulkEditIndexers({ ids: selectedIds, ...payload, }) ); }, [selectedIds, dispatch] ); const onTagsPress = useCallback(() => { setIsTagsModalOpen(true); }, [setIsTagsModalOpen]); const onTagsModalClose = useCallback(() => { setIsTagsModalOpen(false); }, [setIsTagsModalOpen]); const onApplyTagsPress = useCallback( (tags: number[], applyTags: string) => { setIsSavingTags(true); setIsTagsModalOpen(false); dispatch( bulkEditIndexers({ ids: selectedIds, tags, applyTags, }) ); }, [selectedIds, dispatch] ); const onSelectAllChange = useCallback( ({ value }: SelectStateInputProps) => { setSelectState({ type: value ? 'selectAll' : 'unselectAll', items }); }, [items, setSelectState] ); const onSelectedChange = useCallback( ({ id, value, shiftKey = false }) => { setSelectState({ type: 'toggleSelected', items, id, isSelected: value, shiftKey, }); }, [items, setSelectState] ); const errorMessage = getErrorMessage(error, 'Unable to load indexers.'); const anySelected = selectedCount > 0; return ( {translate('ManageIndexers')} {isFetching ? : null} {error ?
{errorMessage}
: null} {isPopulated && !error && !items.length && ( {translate('NoIndexersFound')} )} {isPopulated && !!items.length && !isFetching && !isFetching ? ( {items.map((item) => { return ( ); })}
) : null}
{translate('Delete')} {translate('Edit')} {translate('SetTags')}
); } export default ManageIndexersModalContent;