diff --git a/frontend/src/Series/Delete/DeleteSeriesModal.js b/frontend/src/Series/Delete/DeleteSeriesModal.js deleted file mode 100644 index 556378482..000000000 --- a/frontend/src/Series/Delete/DeleteSeriesModal.js +++ /dev/null @@ -1,34 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import DeleteSeriesModalContentConnector from './DeleteSeriesModalContentConnector'; - -function DeleteSeriesModal(props) { - const { - isOpen, - onModalClose, - ...otherProps - } = props; - - return ( - - - - ); -} - -DeleteSeriesModal.propTypes = { - ...DeleteSeriesModalContentConnector.propTypes, - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default DeleteSeriesModal; diff --git a/frontend/src/Series/Delete/DeleteSeriesModal.tsx b/frontend/src/Series/Delete/DeleteSeriesModal.tsx new file mode 100644 index 000000000..0e32ea9f0 --- /dev/null +++ b/frontend/src/Series/Delete/DeleteSeriesModal.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import Modal from 'Components/Modal/Modal'; +import { sizes } from 'Helpers/Props'; +import DeleteSeriesModalContent, { + DeleteSeriesModalContentProps, +} from './DeleteSeriesModalContent'; + +interface DeleteSeriesModalProps extends DeleteSeriesModalContentProps { + isOpen: boolean; +} + +function DeleteSeriesModal({ + isOpen, + onModalClose, + ...otherProps +}: DeleteSeriesModalProps) { + return ( + + + + ); +} + +export default DeleteSeriesModal; diff --git a/frontend/src/Series/Delete/DeleteSeriesModalContent.js b/frontend/src/Series/Delete/DeleteSeriesModalContent.js deleted file mode 100644 index 233f355e1..000000000 --- a/frontend/src/Series/Delete/DeleteSeriesModalContent.js +++ /dev/null @@ -1,160 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import InlineMarkdown from 'Components/Markdown/InlineMarkdown'; -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 { icons, inputTypes, kinds } from 'Helpers/Props'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import styles from './DeleteSeriesModalContent.css'; - -class DeleteSeriesModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - deleteFiles: false - }; - } - - // - // Listeners - - onDeleteFilesChange = ({ value }) => { - this.setState({ deleteFiles: value }); - }; - - onDeleteSeriesConfirmed = () => { - const deleteFiles = this.state.deleteFiles; - const addImportListExclusion = this.props.deleteOptions.addImportListExclusion; - - this.setState({ deleteFiles: false }); - this.props.onDeletePress(deleteFiles, addImportListExclusion); - }; - - // - // Render - - render() { - const { - title, - path, - statistics = {}, - deleteOptions, - onModalClose, - onDeleteOptionChange - } = this.props; - - const { - episodeFileCount = 0, - sizeOnDisk = 0 - } = statistics; - - const deleteFiles = this.state.deleteFiles; - const addImportListExclusion = deleteOptions.addImportListExclusion; - - return ( - - - {translate('DeleteSeriesModalHeader', { title })} - - - -
- - - {path} -
- - - {translate('AddListExclusion')} - - - - - - {episodeFileCount === 0 ? translate('DeleteSeriesFolder') : translate('DeleteEpisodesFiles', { episodeFileCount })} - - - - - { - deleteFiles ? -
-
- - { - episodeFileCount ? -
- {translate('DeleteSeriesFolderEpisodeCount', { episodeFileCount, size: formatBytes(sizeOnDisk) })} -
: - null - } -
: - null - } -
- - - - - - -
- ); - } -} - -DeleteSeriesModalContent.propTypes = { - title: PropTypes.string.isRequired, - path: PropTypes.string.isRequired, - statistics: PropTypes.object.isRequired, - deleteOptions: PropTypes.object.isRequired, - onDeleteOptionChange: PropTypes.func.isRequired, - onDeletePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -DeleteSeriesModalContent.defaultProps = { - statistics: { - episodeFileCount: 0 - } -}; - -export default DeleteSeriesModalContent; diff --git a/frontend/src/Series/Delete/DeleteSeriesModalContent.tsx b/frontend/src/Series/Delete/DeleteSeriesModalContent.tsx new file mode 100644 index 000000000..96e463f7e --- /dev/null +++ b/frontend/src/Series/Delete/DeleteSeriesModalContent.tsx @@ -0,0 +1,140 @@ +import React, { useCallback, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import AppState from 'App/State/AppState'; +import FormGroup from 'Components/Form/FormGroup'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import Icon from 'Components/Icon'; +import Button from 'Components/Link/Button'; +import InlineMarkdown from 'Components/Markdown/InlineMarkdown'; +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 { icons, inputTypes, kinds } from 'Helpers/Props'; +import { Statistics } from 'Series/Series'; +import useSeries from 'Series/useSeries'; +import { deleteSeries, setDeleteOption } from 'Store/Actions/seriesActions'; +import { CheckInputChanged } from 'typings/inputs'; +import formatBytes from 'Utilities/Number/formatBytes'; +import translate from 'Utilities/String/translate'; +import styles from './DeleteSeriesModalContent.css'; + +export interface DeleteSeriesModalContentProps { + seriesId: number; + onModalClose: () => void; +} + +function DeleteSeriesModalContent({ + seriesId, + onModalClose, +}: DeleteSeriesModalContentProps) { + const dispatch = useDispatch(); + const { title, path, statistics = {} as Statistics } = useSeries(seriesId)!; + const { addImportListExclusion } = useSelector( + (state: AppState) => state.series.deleteOptions + ); + + const { episodeFileCount = 0, sizeOnDisk = 0 } = statistics; + + const [deleteFiles, setDeleteFiles] = useState(false); + + const handleDeleteFilesChange = useCallback( + ({ value }: CheckInputChanged) => { + setDeleteFiles(value); + }, + [] + ); + + const handleDeleteSeriesConfirmed = useCallback(() => { + dispatch( + deleteSeries({ id: seriesId, deleteFiles, addImportListExclusion }) + ); + }, [seriesId, addImportListExclusion, deleteFiles, dispatch]); + + const handleDeleteOptionChange = useCallback( + ({ name, value }: CheckInputChanged) => { + dispatch(setDeleteOption({ [name]: value })); + }, + [dispatch] + ); + + return ( + + + {translate('DeleteSeriesModalHeader', { title })} + + + +
+ + + {path} +
+ + + {translate('AddListExclusion')} + + + + + + + {episodeFileCount === 0 + ? translate('DeleteSeriesFolder') + : translate('DeleteEpisodesFiles', { episodeFileCount })} + + + + + + {deleteFiles ? ( +
+
+ +
+ + {episodeFileCount ? ( +
+ {translate('DeleteSeriesFolderEpisodeCount', { + episodeFileCount, + size: formatBytes(sizeOnDisk), + })} +
+ ) : null} +
+ ) : null} +
+ + + + + + +
+ ); +} + +export default DeleteSeriesModalContent; diff --git a/frontend/src/Series/Delete/DeleteSeriesModalContentConnector.js b/frontend/src/Series/Delete/DeleteSeriesModalContentConnector.js deleted file mode 100644 index 9cc7ddd75..000000000 --- a/frontend/src/Series/Delete/DeleteSeriesModalContentConnector.js +++ /dev/null @@ -1,44 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteSeries, setDeleteOption } from 'Store/Actions/seriesActions'; -import createSeriesSelector from 'Store/Selectors/createSeriesSelector'; -import DeleteSeriesModalContent from './DeleteSeriesModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.series.deleteOptions, - createSeriesSelector(), - (deleteOptions, series) => { - return { - ...series, - deleteOptions - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onDeleteOptionChange(option) { - dispatch( - setDeleteOption({ - [option.name]: option.value - }) - ); - }, - - onDeletePress(deleteFiles, addImportListExclusion) { - dispatch( - deleteSeries({ - id: props.seriesId, - deleteFiles, - addImportListExclusion - }) - ); - - props.onModalClose(true); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(DeleteSeriesModalContent); diff --git a/frontend/src/Series/Series.ts b/frontend/src/Series/Series.ts index b35b90d6b..183371987 100644 --- a/frontend/src/Series/Series.ts +++ b/frontend/src/Series/Series.ts @@ -90,7 +90,7 @@ interface Series extends ModelBase { seasons: Season[]; seriesType: SeriesType; sortTitle: string; - statistics: Statistics; + statistics?: Statistics; status: SeriesStatus; tags: number[]; title: string;