1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-25 22:46:31 -04:00

Convert Manual Import to Typescript

This commit is contained in:
Mark McDowall
2023-03-27 16:48:55 -07:00
parent 032d9a720c
commit defdc84b7e
63 changed files with 2946 additions and 3528 deletions
@@ -1,37 +0,0 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Modal from 'Components/Modal/Modal';
import SelectSeriesModalContentConnector from './SelectSeriesModalContentConnector';
class SelectSeriesModal extends Component {
//
// Render
render() {
const {
isOpen,
onModalClose,
...otherProps
} = this.props;
return (
<Modal
isOpen={isOpen}
onModalClose={onModalClose}
>
<SelectSeriesModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
</Modal>
);
}
}
SelectSeriesModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default SelectSeriesModal;
@@ -0,0 +1,27 @@
import React from 'react';
import Modal from 'Components/Modal/Modal';
import Series from 'Series/Series';
import SelectSeriesModalContent from './SelectSeriesModalContent';
interface SelectSeriesModalProps {
isOpen: boolean;
modalTitle: string;
onSeriesSelect(series: Series): void;
onModalClose(): void;
}
function SelectSeriesModal(props: SelectSeriesModalProps) {
const { isOpen, modalTitle, onSeriesSelect, onModalClose } = props;
return (
<Modal isOpen={isOpen} onModalClose={onModalClose}>
<SelectSeriesModalContent
modalTitle={modalTitle}
onSeriesSelect={onSeriesSelect}
onModalClose={onModalClose}
/>
</Modal>
);
}
export default SelectSeriesModal;
@@ -1,105 +0,0 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import TextInput from 'Components/Form/TextInput';
import Button from 'Components/Link/Button';
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 Scroller from 'Components/Scroller/Scroller';
import { scrollDirections } from 'Helpers/Props';
import SelectSeriesRow from './SelectSeriesRow';
import styles from './SelectSeriesModalContent.css';
class SelectSeriesModalContent extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
filter: ''
};
}
//
// Listeners
onFilterChange = ({ value }) => {
this.setState({ filter: value });
};
//
// Render
render() {
const {
items,
modalTitle,
onSeriesSelect,
onModalClose
} = this.props;
const filter = this.state.filter;
const filterLower = filter.toLowerCase();
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{modalTitle} - Select Series
</ModalHeader>
<ModalBody
className={styles.modalBody}
scrollDirection={scrollDirections.NONE}
>
<TextInput
className={styles.filterInput}
placeholder="Filter series"
name="filter"
value={filter}
autoFocus={true}
onChange={this.onFilterChange}
/>
<Scroller
className={styles.scroller}
autoFocus={false}
>
{
items.map((item) => {
return item.title.toLowerCase().includes(filterLower) ?
(
<SelectSeriesRow
key={item.id}
id={item.id}
title={item.title}
onSeriesSelect={onSeriesSelect}
/>
) :
null;
})
}
</Scroller>
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>
Cancel
</Button>
</ModalFooter>
</ModalContent>
);
}
}
SelectSeriesModalContent.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
modalTitle: PropTypes.string.isRequired,
onSeriesSelect: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default SelectSeriesModalContent;
@@ -0,0 +1,92 @@
import React, { useCallback, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import TextInput from 'Components/Form/TextInput';
import Button from 'Components/Link/Button';
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 Scroller from 'Components/Scroller/Scroller';
import { scrollDirections } from 'Helpers/Props';
import Series from 'Series/Series';
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
import SelectSeriesRow from './SelectSeriesRow';
import styles from './SelectSeriesModalContent.css';
interface SelectSeriesModalContentProps {
modalTitle: string;
onSeriesSelect(series: Series): void;
onModalClose(): void;
}
function SelectSeriesModalContent(props: SelectSeriesModalContentProps) {
const { modalTitle, onSeriesSelect, onModalClose } = props;
const allSeries = useSelector(createAllSeriesSelector());
const [filter, setFilter] = useState('');
const onFilterChange = useCallback(
({ value }) => {
setFilter(value);
},
[setFilter]
);
const onSeriesSelectWrapper = useCallback(
(seriesId: number) => {
const series = allSeries.find((s) => s.id === seriesId);
onSeriesSelect(series);
},
[allSeries, onSeriesSelect]
);
const items = useMemo(() => {
const sorted = [...allSeries].sort((a, b) =>
a.sortTitle.localeCompare(b.sortTitle)
);
return sorted.filter((item) =>
item.title.toLowerCase().includes(filter.toLowerCase())
);
}, [allSeries, filter]);
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>{modalTitle} - Select Series</ModalHeader>
<ModalBody
className={styles.modalBody}
scrollDirection={scrollDirections.NONE}
>
<TextInput
className={styles.filterInput}
placeholder="Filter series"
name="filter"
value={filter}
autoFocus={true}
onChange={onFilterChange}
/>
<Scroller className={styles.scroller} autoFocus={false}>
{items.map((item) => {
return (
<SelectSeriesRow
key={item.id}
id={item.id}
title={item.title}
onSeriesSelect={onSeriesSelectWrapper}
/>
);
})}
</Scroller>
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>Cancel</Button>
</ModalFooter>
</ModalContent>
);
}
export default SelectSeriesModalContent;
@@ -1,86 +0,0 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { reprocessInteractiveImportItems, updateInteractiveImportItem } from 'Store/Actions/interactiveImportActions';
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
import SelectSeriesModalContent from './SelectSeriesModalContent';
function createMapStateToProps() {
return createSelector(
createAllSeriesSelector(),
(items) => {
return {
items: [...items].sort((a, b) => {
if (a.sortTitle < b.sortTitle) {
return -1;
}
if (a.sortTitle > b.sortTitle) {
return 1;
}
return 0;
})
};
}
);
}
const mapDispatchToProps = {
dispatchReprocessInteractiveImportItems: reprocessInteractiveImportItems,
dispatchUpdateInteractiveImportItem: updateInteractiveImportItem
};
class SelectSeriesModalContentConnector extends Component {
//
// Listeners
onSeriesSelect = (seriesId) => {
const {
ids,
items,
dispatchUpdateInteractiveImportItem,
dispatchReprocessInteractiveImportItems,
onModalClose
} = this.props;
const series = items.find((s) => s.id === seriesId);
ids.forEach((id) => {
dispatchUpdateInteractiveImportItem({
id,
series,
seasonNumber: undefined,
episodes: []
});
});
dispatchReprocessInteractiveImportItems({ ids });
onModalClose(true);
};
//
// Render
render() {
return (
<SelectSeriesModalContent
{...this.props}
onSeriesSelect={this.onSeriesSelect}
/>
);
}
}
SelectSeriesModalContentConnector.propTypes = {
ids: PropTypes.arrayOf(PropTypes.number).isRequired,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
dispatchReprocessInteractiveImportItems: PropTypes.func.isRequired,
dispatchUpdateInteractiveImportItem: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(SelectSeriesModalContentConnector);