Typings cleanup and improvements

(cherry picked from commit b2c43fb2a67965d68d3d35b72302b0cddb5aca23)
This commit is contained in:
Mark McDowall
2023-04-04 09:21:34 -07:00
committed by Bogdan
parent 5764950b10
commit 4bfaab4b21
45 changed files with 468 additions and 319 deletions
+20 -13
View File
@@ -1,6 +1,10 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { SelectProvider } from 'App/SelectContext';
import ClientSideCollectionAppState from 'App/State/ClientSideCollectionAppState';
import IndexerAppState, {
IndexerIndexAppState,
} from 'App/State/IndexerAppState';
import { APP_INDEXER_SYNC } from 'Commands/commandNames';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import PageContent from 'Components/Page/PageContent';
@@ -64,19 +68,20 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
sortKey,
sortDirection,
view,
} = useSelector(
createIndexerClientSideCollectionItemsSelector('indexerIndex')
);
}: IndexerAppState & IndexerIndexAppState & ClientSideCollectionAppState =
useSelector(createIndexerClientSideCollectionItemsSelector('indexerIndex'));
const isSyncingIndexers = useSelector(
createCommandExecutingSelector(APP_INDEXER_SYNC)
);
const { isSmallScreen } = useSelector(createDimensionsSelector());
const dispatch = useDispatch();
const scrollerRef = useRef<HTMLDivElement>();
const scrollerRef = useRef<HTMLDivElement>(null);
const [isAddIndexerModalOpen, setIsAddIndexerModalOpen] = useState(false);
const [isEditIndexerModalOpen, setIsEditIndexerModalOpen] = useState(false);
const [jumpToCharacter, setJumpToCharacter] = useState<string | null>(null);
const [jumpToCharacter, setJumpToCharacter] = useState<string | undefined>(
undefined
);
const [isSelectMode, setIsSelectMode] = useState(false);
const onAppIndexerSyncPress = useCallback(() => {
@@ -112,37 +117,37 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
}, [isSelectMode, setIsSelectMode]);
const onTableOptionChange = useCallback(
(payload) => {
(payload: unknown) => {
dispatch(setIndexerTableOption(payload));
},
[dispatch]
);
const onSortSelect = useCallback(
(value) => {
(value: string) => {
dispatch(setIndexerSort({ sortKey: value }));
},
[dispatch]
);
const onFilterSelect = useCallback(
(value) => {
(value: string) => {
dispatch(setIndexerFilter({ selectedFilterKey: value }));
},
[dispatch]
);
const onJumpBarItemPress = useCallback(
(character) => {
(character: string) => {
setJumpToCharacter(character);
},
[setJumpToCharacter]
);
const onScroll = useCallback(
({ scrollTop }) => {
setJumpToCharacter(null);
scrollPositions.seriesIndex = scrollTop;
({ scrollTop }: { scrollTop: number }) => {
setJumpToCharacter(undefined);
scrollPositions.indexerIndex = scrollTop;
},
[setJumpToCharacter]
);
@@ -155,7 +160,7 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
};
}
const characters = items.reduce((acc, item) => {
const characters = items.reduce((acc: Record<string, number>, item) => {
let char = item.sortName.charAt(0);
if (!isNaN(Number(char))) {
@@ -277,6 +282,8 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
<PageContentBody
ref={scrollerRef}
className={styles.contentBody}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
innerClassName={styles[`${view}InnerContentBody`]}
initialScrollTop={props.initialScrollTop}
onScroll={onScroll}
@@ -1,12 +1,13 @@
import React, { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import FilterModal from 'Components/Filter/FilterModal';
import { setIndexerFilter } from 'Store/Actions/indexerIndexActions';
function createIndexerSelector() {
return createSelector(
(state) => state.indexers.items,
(state: AppState) => state.indexers.items,
(indexers) => {
return indexers;
}
@@ -15,14 +16,20 @@ function createIndexerSelector() {
function createFilterBuilderPropsSelector() {
return createSelector(
(state) => state.indexerIndex.filterBuilderProps,
(state: AppState) => state.indexerIndex.filterBuilderProps,
(filterBuilderProps) => {
return filterBuilderProps;
}
);
}
export default function IndexerIndexFilterModal(props) {
interface IndexerIndexFilterModalProps {
isOpen: boolean;
}
export default function IndexerIndexFilterModal(
props: IndexerIndexFilterModalProps
) {
const sectionItems = useSelector(createIndexerSelector());
const filterBuilderProps = useSelector(createFilterBuilderPropsSelector());
const customFilterType = 'indexerIndex';
@@ -30,7 +37,7 @@ export default function IndexerIndexFilterModal(props) {
const dispatch = useDispatch();
const dispatchSetFilter = useCallback(
(payload) => {
(payload: unknown) => {
dispatch(setIndexerFilter(payload));
},
[dispatch]
@@ -38,6 +45,7 @@ export default function IndexerIndexFilterModal(props) {
return (
<FilterModal
// TODO: Don't spread all the props
{...props}
sectionItems={sectionItems}
filterBuilderProps={filterBuilderProps}
@@ -3,6 +3,7 @@ import React from 'react';
import { useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import { ColorImpairedConsumer } from 'App/ColorImpairedContext';
import IndexerAppState from 'App/State/IndexerAppState';
import DescriptionList from 'Components/DescriptionList/DescriptionList';
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
@@ -13,7 +14,7 @@ import styles from './IndexerIndexFooter.css';
function createUnoptimizedSelector() {
return createSelector(
createClientSideCollectionSelector('indexers', 'indexerIndex'),
(indexers) => {
(indexers: IndexerAppState) => {
return indexers.items.map((s) => {
const { protocol, privacy, enable } = s;
@@ -1,10 +1,18 @@
import PropTypes from 'prop-types';
import React from 'react';
import { CustomFilter } from 'App/State/AppState';
import FilterMenu from 'Components/Menu/FilterMenu';
import { align } from 'Helpers/Props';
import IndexerIndexFilterModal from 'Indexer/Index/IndexerIndexFilterModal';
function IndexerIndexFilterMenu(props) {
interface IndexerIndexFilterMenuProps {
selectedFilterKey: string | number;
filters: object[];
customFilters: CustomFilter[];
isDisabled: boolean;
onFilterSelect(filterName: string): unknown;
}
function IndexerIndexFilterMenu(props: IndexerIndexFilterMenuProps) {
const {
selectedFilterKey,
filters,
@@ -26,15 +34,6 @@ function IndexerIndexFilterMenu(props) {
);
}
IndexerIndexFilterMenu.propTypes = {
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
.isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
isDisabled: PropTypes.bool.isRequired,
onFilterSelect: PropTypes.func.isRequired,
};
IndexerIndexFilterMenu.defaultProps = {
showCustomFilters: false,
};
@@ -1,12 +1,19 @@
import PropTypes from 'prop-types';
import React from 'react';
import MenuContent from 'Components/Menu/MenuContent';
import SortMenu from 'Components/Menu/SortMenu';
import SortMenuItem from 'Components/Menu/SortMenuItem';
import { align, sortDirections } from 'Helpers/Props';
import { align } from 'Helpers/Props';
import SortDirection from 'Helpers/Props/SortDirection';
import translate from 'Utilities/String/translate';
function IndexerIndexSortMenu(props) {
interface IndexerIndexSortMenuProps {
sortKey?: string;
sortDirection?: SortDirection;
isDisabled: boolean;
onSortSelect(sortKey: string): unknown;
}
function IndexerIndexSortMenu(props: IndexerIndexSortMenuProps) {
const { sortKey, sortDirection, isDisabled, onSortSelect } = props;
return (
@@ -79,11 +86,4 @@ function IndexerIndexSortMenu(props) {
);
}
IndexerIndexSortMenu.propTypes = {
sortKey: PropTypes.string,
sortDirection: PropTypes.oneOf(sortDirections.all),
isDisabled: PropTypes.bool.isRequired,
onSortSelect: PropTypes.func.isRequired,
};
export default IndexerIndexSortMenu;
@@ -7,6 +7,7 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { kinds } from 'Helpers/Props';
import Indexer from 'Indexer/Indexer';
import { bulkDeleteIndexers } from 'Store/Actions/indexerActions';
import createAllIndexersSelector from 'Store/Selectors/createAllIndexersSelector';
import translate from 'Utilities/String/translate';
@@ -20,15 +21,15 @@ interface DeleteIndexerModalContentProps {
function DeleteIndexerModalContent(props: DeleteIndexerModalContentProps) {
const { indexerIds, onModalClose } = props;
const allIndexers = useSelector(createAllIndexersSelector());
const allIndexers: Indexer[] = useSelector(createAllIndexersSelector());
const dispatch = useDispatch();
const selectedIndexers = useMemo(() => {
const indexers = indexerIds.map((id) => {
const indexers = useMemo((): Indexer[] => {
const indexerList = indexerIds.map((id) => {
return allIndexers.find((s) => s.id === id);
});
}) as Indexer[];
return orderBy(indexers, ['sortName']);
return orderBy(indexerList, ['sortName']);
}, [indexerIds, allIndexers]);
const onDeleteIndexerConfirmed = useCallback(() => {
@@ -47,13 +48,11 @@ function DeleteIndexerModalContent(props: DeleteIndexerModalContentProps) {
<ModalBody>
<div className={styles.message}>
{translate('DeleteSelectedIndexersMessageText', [
selectedIndexers.length,
])}
{translate('DeleteSelectedIndexersMessageText', [indexers.length])}
</div>
<ul>
{selectedIndexers.map((s) => {
{indexers.map((s) => {
return (
<li key={s.id}>
<span>{s.name}</span>
@@ -107,7 +107,7 @@ function EditIndexerModalContent(props: EditIndexerModalContentProps) {
]);
const onInputChange = useCallback(
({ name, value }) => {
({ name, value }: { name: string; value: string }) => {
switch (name) {
case 'enable':
setEnable(value);
@@ -7,7 +7,7 @@ import translate from 'Utilities/String/translate';
interface IndexerIndexSelectAllButtonProps {
label: string;
isSelectMode: boolean;
overflowComponent: React.FunctionComponent;
overflowComponent: React.FunctionComponent<never>;
}
function IndexerIndexSelectAllButton(props: IndexerIndexSelectAllButtonProps) {
@@ -15,6 +15,16 @@ import EditIndexerModal from './Edit/EditIndexerModal';
import TagsModal from './Tags/TagsModal';
import styles from './IndexerIndexSelectFooter.css';
interface SavePayload {
enable?: boolean;
appProfileId?: number;
priority?: number;
minimumSeeders?: number;
seedRatio?: number;
seedTime?: number;
packSeedTime?: number;
}
const indexersEditorSelector = createSelector(
(state: AppState) => state.indexers,
(indexers) => {
@@ -60,7 +70,7 @@ function IndexerIndexSelectFooter() {
}, [setIsEditModalOpen]);
const onSavePress = useCallback(
(payload) => {
(payload: SavePayload) => {
setIsSavingIndexer(true);
setIsEditModalOpen(false);
@@ -83,7 +93,7 @@ function IndexerIndexSelectFooter() {
}, [setIsTagsModalOpen]);
const onApplyTagsPress = useCallback(
(tags, applyTags) => {
(tags: number[], applyTags: string) => {
setIsSavingTags(true);
setIsTagsModalOpen(false);
@@ -7,7 +7,7 @@ interface IndexerIndexSelectModeButtonProps {
label: string;
iconName: IconDefinition;
isSelectMode: boolean;
overflowComponent: React.FunctionComponent;
overflowComponent: React.FunctionComponent<never>;
onPress: () => void;
}
@@ -1,6 +1,7 @@
import { concat, uniq } from 'lodash';
import { uniq } from 'lodash';
import React, { useCallback, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { Tag } from 'App/State/TagsAppState';
import Form from 'Components/Form/Form';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
@@ -12,6 +13,7 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
import Indexer from 'Indexer/Indexer';
import createAllIndexersSelector from 'Store/Selectors/createAllIndexersSelector';
import createTagsSelector from 'Store/Selectors/createTagsSelector';
import translate from 'Utilities/String/translate';
@@ -26,29 +28,35 @@ interface TagsModalContentProps {
function TagsModalContent(props: TagsModalContentProps) {
const { indexerIds, onModalClose, onApplyTagsPress } = props;
const allIndexers = useSelector(createAllIndexersSelector());
const tagList = useSelector(createTagsSelector());
const allIndexers: Indexer[] = useSelector(createAllIndexersSelector());
const tagList: Tag[] = useSelector(createTagsSelector());
const [tags, setTags] = useState<number[]>([]);
const [applyTags, setApplyTags] = useState('add');
const indexerTags = useMemo(() => {
const indexers = indexerIds.map((id) => {
return allIndexers.find((s) => s.id === id);
});
const tags = indexerIds.reduce((acc: number[], id) => {
const s = allIndexers.find((s) => s.id === id);
return uniq(concat(...indexers.map((s) => s.tags)));
if (s) {
acc.push(...s.tags);
}
return acc;
}, []);
return uniq(tags);
}, [indexerIds, allIndexers]);
const onTagsChange = useCallback(
({ value }) => {
({ value }: { value: number[] }) => {
setTags(value);
},
[setTags]
);
const onApplyTagsChange = useCallback(
({ value }) => {
({ value }: { value: string }) => {
setApplyTags(value);
},
[setApplyTags]
@@ -13,6 +13,7 @@ import DeleteIndexerModal from 'Indexer/Delete/DeleteIndexerModal';
import EditIndexerModalConnector from 'Indexer/Edit/EditIndexerModalConnector';
import createIndexerIndexItemSelector from 'Indexer/Index/createIndexerIndexItemSelector';
import IndexerTitleLink from 'Indexer/IndexerTitleLink';
import { SelectStateInputProps } from 'typings/props';
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
import translate from 'Utilities/String/translate';
import CapabilitiesLabel from './CapabilitiesLabel';
@@ -100,12 +101,8 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
setIsDeleteIndexerModalOpen(false);
}, [setIsDeleteIndexerModalOpen]);
const checkInputCallback = useCallback(() => {
// Mock handler to satisfy `onChange` being required for `CheckInput`.
}, []);
const onSelectedChange = useCallback(
({ id, value, shiftKey }) => {
({ id, value, shiftKey }: SelectStateInputProps) => {
selectDispatch({
type: 'toggleSelected',
id,
@@ -202,6 +199,8 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
if (name === 'added') {
return (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ts(2739)
<RelativeDateCellConnector
key={name}
className={styles[name]}
@@ -213,6 +212,8 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
if (name === 'vipExpiration') {
return (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ts(2739)
<RelativeDateCellConnector
key={name}
className={styles[name]}
@@ -266,6 +267,8 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
return (
<VirtualTableRowCell
key={column.name}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ts(2739)
className={styles[column.name]}
>
<IconButton
@@ -1,8 +1,9 @@
import { throttle } from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import React, { RefObject, useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import { FixedSizeList as List, ListChildComponentProps } from 'react-window';
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import Scroller from 'Components/Scroller/Scroller';
import Column from 'Components/Table/Column';
import useMeasure from 'Helpers/Hooks/useMeasure';
@@ -13,7 +14,6 @@ import dimensions from 'Styles/Variables/dimensions';
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
import IndexerIndexRow from './IndexerIndexRow';
import IndexerIndexTableHeader from './IndexerIndexTableHeader';
import selectTableOptions from './selectTableOptions';
import styles from './IndexerIndexTable.css';
const bodyPadding = parseInt(dimensions.pageContentBodyPadding);
@@ -30,17 +30,17 @@ interface RowItemData {
interface IndexerIndexTableProps {
items: Indexer[];
sortKey?: string;
sortKey: string;
sortDirection?: SortDirection;
jumpToCharacter?: string;
scrollTop?: number;
scrollerRef: React.MutableRefObject<HTMLElement>;
scrollerRef: RefObject<HTMLElement>;
isSelectMode: boolean;
isSmallScreen: boolean;
}
const columnsSelector = createSelector(
(state) => state.indexerIndex.columns,
(state: AppState) => state.indexerIndex.columns,
(columns) => columns
);
@@ -91,22 +91,21 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
} = props;
const columns = useSelector(columnsSelector);
const { showBanners } = useSelector(selectTableOptions);
const listRef = useRef<List>(null);
const listRef = useRef<List<RowItemData>>(null);
const [measureRef, bounds] = useMeasure();
const [size, setSize] = useState({ width: 0, height: 0 });
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const rowHeight = useMemo(() => {
return showBanners ? 70 : 38;
}, [showBanners]);
const rowHeight = 38;
useEffect(() => {
const current = scrollerRef.current as HTMLElement;
const current = scrollerRef?.current as HTMLElement;
if (isSmallScreen) {
setSize({
width: window.innerWidth,
height: window.innerHeight,
width: windowWidth,
height: windowHeight,
});
return;
@@ -119,10 +118,10 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
setSize({
width: width - padding * 2,
height: window.innerHeight,
height: windowHeight,
});
}
}, [isSmallScreen, scrollerRef, bounds]);
}, [isSmallScreen, windowWidth, windowHeight, scrollerRef, bounds]);
useEffect(() => {
const currentScrollerRef = scrollerRef.current as HTMLElement;
@@ -165,7 +164,7 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
}
listRef.current?.scrollTo(scrollTop);
scrollerRef.current?.scrollTo(0, scrollTop);
scrollerRef?.current?.scrollTo(0, scrollTop);
}
}
}, [jumpToCharacter, rowHeight, items, scrollerRef, listRef]);
@@ -177,7 +176,6 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
scrollDirection={ScrollDirection.Horizontal}
>
<IndexerIndexTableHeader
showBanners={showBanners}
columns={columns}
sortKey={sortKey}
sortDirection={sortDirection}
@@ -14,12 +14,11 @@ import {
setIndexerSort,
setIndexerTableOption,
} from 'Store/Actions/indexerIndexActions';
import { SelectStateInputProps } from 'typings/props';
import { CheckInputChanged } from 'typings/inputs';
import IndexerIndexTableOptions from './IndexerIndexTableOptions';
import styles from './IndexerIndexTableHeader.css';
interface IndexerIndexTableHeaderProps {
showBanners: boolean;
columns: Column[];
sortKey?: string;
sortDirection?: SortDirection;
@@ -32,21 +31,21 @@ function IndexerIndexTableHeader(props: IndexerIndexTableHeaderProps) {
const [selectState, selectDispatch] = useSelect();
const onSortPress = useCallback(
(value) => {
(value: string) => {
dispatch(setIndexerSort({ sortKey: value }));
},
[dispatch]
);
const onTableOptionChange = useCallback(
(payload) => {
(payload: unknown) => {
dispatch(setIndexerTableOption(payload));
},
[dispatch]
);
const onSelectAllChange = useCallback(
({ value }: SelectStateInputProps) => {
({ value }: CheckInputChanged) => {
selectDispatch({
type: value ? 'selectAll' : 'unselectAll',
});
@@ -93,7 +92,11 @@ function IndexerIndexTableHeader(props: IndexerIndexTableHeaderProps) {
return (
<VirtualTableHeaderCell
key={name}
className={classNames(styles[name])}
className={classNames(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
styles[name]
)}
name={name}
sortKey={sortKey}
sortDirection={sortDirection}
@@ -4,6 +4,7 @@ import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import { inputTypes } from 'Helpers/Props';
import { CheckInputChanged } from 'typings/inputs';
import translate from 'Utilities/String/translate';
import selectTableOptions from './selectTableOptions';
@@ -19,7 +20,7 @@ function IndexerIndexTableOptions(props: IndexerIndexTableOptionsProps) {
const { showSearchAction } = tableOptions;
const onTableOptionChangeWrapper = useCallback(
({ name, value }) => {
({ name, value }: CheckInputChanged) => {
onTableOptionChange({
tableOptions: {
...tableOptions,
@@ -11,6 +11,8 @@ function ProtocolLabel(props: ProtocolLabelProps) {
const protocolName = protocol === 'usenet' ? 'nzb' : protocol;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ts(7053)
return <Label className={styles[protocol]}>{protocolName}</Label>;
}
@@ -1,7 +1,8 @@
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
const selectTableOptions = createSelector(
(state) => state.indexerIndex.tableOptions,
(state: AppState) => state.indexerIndex.tableOptions,
(tableOptions) => tableOptions
);
@@ -1,26 +1,17 @@
import { createSelector } from 'reselect';
import Indexer from 'Indexer/Indexer';
import createIndexerAppProfileSelector from 'Store/Selectors/createIndexerAppProfileSelector';
import createIndexerSelector from 'Store/Selectors/createIndexerSelector';
import { createIndexerSelectorForHook } from 'Store/Selectors/createIndexerSelector';
import createIndexerStatusSelector from 'Store/Selectors/createIndexerStatusSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
function createIndexerIndexItemSelector(indexerId: number) {
return createSelector(
createIndexerSelector(indexerId),
createIndexerSelectorForHook(indexerId),
createIndexerAppProfileSelector(indexerId),
createIndexerStatusSelector(indexerId),
createUISettingsSelector(),
(indexer: Indexer, appProfile, status, uiSettings) => {
// If a series is deleted this selector may fire before the parent
// selectors, which will result in an undefined series, if that happens
// we want to return early here and again in the render function to avoid
// trying to show a series that has no information available.
if (!indexer) {
return {};
}
return {
indexer,
appProfile,
+1
View File
@@ -45,6 +45,7 @@ interface Indexer extends ModelBase {
priority: number;
fields: IndexerField[];
tags: number[];
sortName: string;
status: IndexerStatus;
capabilities: IndexerCapabilities;
indexerUrls: string[];
@@ -22,13 +22,13 @@ import { kinds } from 'Helpers/Props';
import DeleteIndexerModal from 'Indexer/Delete/DeleteIndexerModal';
import EditIndexerModalConnector from 'Indexer/Edit/EditIndexerModalConnector';
import Indexer from 'Indexer/Indexer';
import createIndexerSelector from 'Store/Selectors/createIndexerSelector';
import { createIndexerSelectorForHook } from 'Store/Selectors/createIndexerSelector';
import translate from 'Utilities/String/translate';
import styles from './IndexerInfoModalContent.css';
function createIndexerInfoItemSelector(indexerId: number) {
return createSelector(
createIndexerSelector(indexerId),
createIndexerSelectorForHook(indexerId),
(indexer: Indexer) => {
return {
indexer,
@@ -130,9 +130,13 @@ function IndexerInfoModalContent(props: IndexerInfoModalContentProps) {
{translate('IndexerSite')}
</DescriptionListItemTitle>
<DescriptionListItemDescription>
<Link to={baseUrl}>
{baseUrl.replace(/(:\/\/)api\./, '$1')}
</Link>
{baseUrl ? (
<Link to={baseUrl}>
{baseUrl.replace(/(:\/\/)api\./, '$1')}
</Link>
) : (
'-'
)}
</DescriptionListItemDescription>
<DescriptionListItemTitle>
{protocol === 'usenet'