diff --git a/frontend/src/Series/MonitoringOptions/MonitoringOptionModalConnector.js b/frontend/src/Series/MonitoringOptions/MonitoringOptionModalConnector.js
deleted file mode 100644
index 44b412613..000000000
--- a/frontend/src/Series/MonitoringOptions/MonitoringOptionModalConnector.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import MonitoringOptionsModal from './MonitoringOptionsModal';
-
-const mapDispatchToProps = {
- clearPendingChanges
-};
-
-class MonitoringOptionsModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.clearPendingChanges({ section: 'series' });
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MonitoringOptionsModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(undefined, mapDispatchToProps)(MonitoringOptionsModalConnector);
diff --git a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModal.js b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModal.js
deleted file mode 100644
index 4071e7f9a..000000000
--- a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModal.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import MonitoringOptionsModalContentConnector from './MonitoringOptionsModalContentConnector';
-
-function MonitoringOptionsModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-MonitoringOptionsModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default MonitoringOptionsModal;
diff --git a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModal.tsx b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModal.tsx
new file mode 100644
index 000000000..48323de50
--- /dev/null
+++ b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModal.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import Modal from 'Components/Modal/Modal';
+import MonitoringOptionsModalContent, {
+ MonitoringOptionsModalContentProps,
+} from './MonitoringOptionsModalContent';
+
+interface MonitoringOptionsModalProps
+ extends MonitoringOptionsModalContentProps {
+ isOpen: boolean;
+}
+
+function MonitoringOptionsModal({
+ isOpen,
+ onModalClose,
+ ...otherProps
+}: MonitoringOptionsModalProps) {
+ return (
+
+
+
+ );
+}
+
+export default MonitoringOptionsModal;
diff --git a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContent.js b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContent.js
deleted file mode 100644
index 61024f1c4..000000000
--- a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContent.js
+++ /dev/null
@@ -1,151 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import SeriesMonitoringOptionsPopoverContent from 'AddSeries/SeriesMonitoringOptionsPopoverContent';
-import Form from 'Components/Form/Form';
-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 SpinnerButton from 'Components/Link/SpinnerButton';
-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 Popover from 'Components/Tooltip/Popover';
-import { icons, inputTypes, tooltipPositions } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './MonitoringOptionsModalContent.css';
-
-const NO_CHANGE = 'noChange';
-
-class MonitoringOptionsModalContent extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- monitor: NO_CHANGE
- };
- }
-
- componentDidUpdate(prevProps) {
- const {
- isSaving,
- saveError
- } = this.props;
-
- if (prevProps.isSaving && !isSaving && !saveError) {
- this.setState({
- monitor: NO_CHANGE
- });
- }
- }
-
- onInputChange = ({ name, value }) => {
- this.setState({ [name]: value });
- };
-
- //
- // Listeners
-
- onSavePress = () => {
- const {
- onSavePress
- } = this.props;
- const {
- monitor
- } = this.state;
-
- if (monitor !== NO_CHANGE) {
- onSavePress({ monitor });
- }
- };
-
- //
- // Render
-
- render() {
- const {
- isSaving,
- onInputChange,
- onModalClose,
- ...otherProps
- } = this.props;
-
- const {
- monitor
- } = this.state;
-
- return (
-
-
- {translate('MonitorSeries')}
-
-
-
-
-
-
-
-
-
-
- {translate('Save')}
-
-
-
- );
- }
-}
-
-MonitoringOptionsModalContent.propTypes = {
- seriesId: PropTypes.number.isRequired,
- saveError: PropTypes.object,
- isSaving: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-MonitoringOptionsModalContent.defaultProps = {
- isSaving: false
-};
-
-export default MonitoringOptionsModalContent;
diff --git a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContent.tsx b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContent.tsx
new file mode 100644
index 000000000..15780bc20
--- /dev/null
+++ b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContent.tsx
@@ -0,0 +1,107 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import SeriesMonitoringOptionsPopoverContent from 'AddSeries/SeriesMonitoringOptionsPopoverContent';
+import AppState from 'App/State/AppState';
+import Form from 'Components/Form/Form';
+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 SpinnerButton from 'Components/Link/SpinnerButton';
+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 Popover from 'Components/Tooltip/Popover';
+import usePrevious from 'Helpers/Hooks/usePrevious';
+import { icons, tooltipPositions } from 'Helpers/Props';
+import { updateSeriesMonitor } from 'Store/Actions/seriesActions';
+import { InputChanged } from 'typings/inputs';
+import translate from 'Utilities/String/translate';
+import styles from './MonitoringOptionsModalContent.css';
+
+const NO_CHANGE = 'noChange';
+
+export interface MonitoringOptionsModalContentProps {
+ seriesId: number;
+ onModalClose: () => void;
+}
+
+function MonitoringOptionsModalContent({
+ seriesId,
+ onModalClose,
+}: MonitoringOptionsModalContentProps) {
+ const dispatch = useDispatch();
+ const { isSaving, saveError } = useSelector(
+ (state: AppState) => state.series
+ );
+
+ const [monitor, setMonitor] = useState(NO_CHANGE);
+ const wasSaving = usePrevious(isSaving);
+
+ const handleMonitorChange = useCallback(({ value }: InputChanged) => {
+ setMonitor(value);
+ }, []);
+
+ const handleSavePress = useCallback(() => {
+ if (monitor === NO_CHANGE) {
+ return;
+ }
+
+ dispatch(
+ updateSeriesMonitor({
+ seriesIds: [seriesId],
+ monitor,
+ shouldFetchEpisodesAfterUpdate: true,
+ })
+ );
+ }, [monitor, seriesId, dispatch]);
+
+ useEffect(() => {
+ if (!isSaving && wasSaving && !saveError) {
+ onModalClose();
+ }
+ }, [isSaving, wasSaving, saveError, onModalClose]);
+
+ return (
+
+ {translate('MonitorSeries')}
+
+
+
+
+
+
+
+
+
+ {translate('Save')}
+
+
+
+ );
+}
+
+export default MonitoringOptionsModalContent;
diff --git a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContentConnector.js b/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContentConnector.js
deleted file mode 100644
index 1d4772a14..000000000
--- a/frontend/src/Series/MonitoringOptions/MonitoringOptionsModalContentConnector.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { updateSeriesMonitor } from 'Store/Actions/seriesActions';
-import MonitoringOptionsModalContent from './MonitoringOptionsModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.series,
- (seriesState) => {
- const {
- isSaving,
- saveError
- } = seriesState;
-
- return {
- isSaving,
- saveError
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchUpdateMonitoringOptions: updateSeriesMonitor
-};
-
-class MonitoringOptionsModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose(true);
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.setState({ name, value });
- };
-
- onSavePress = ({ monitor }) => {
- this.props.dispatchUpdateMonitoringOptions({
- seriesIds: [this.props.seriesId],
- monitor,
- shouldFetchEpisodesAfterUpdate: true
- });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MonitoringOptionsModalContentConnector.propTypes = {
- seriesId: PropTypes.number.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- dispatchUpdateMonitoringOptions: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(MonitoringOptionsModalContentConnector);