(cherry picked from commit 428569106499b5e3a463f1990ae2996d1ae4ab49) Persist page size for Import List Exclusions (cherry picked from commit e81bb3b993adac705fd61dc9e281b040ca2338f5) Clear pending changes for edit import list exclusions on modal close (cherry picked from commit 7b87de2e93c2aa499cff224f84253ba944bb58d4) Fixed actions column width for import list exclusions (cherry picked from commit d691ad8e12ea4f2bc77f0b551c17d22d91c4ba22)pull/10287/head
parent
b1a7652753
commit
b6d9c73a17
@ -0,0 +1,54 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
interface PagingOptions {
|
||||
page: number;
|
||||
totalPages: number;
|
||||
gotoPage: ({ page }: { page: number }) => void;
|
||||
}
|
||||
|
||||
function usePaging(options: PagingOptions) {
|
||||
const { page, totalPages, gotoPage } = options;
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleFirstPagePress = useCallback(() => {
|
||||
dispatch(gotoPage({ page: 1 }));
|
||||
}, [dispatch, gotoPage]);
|
||||
|
||||
const handlePreviousPagePress = useCallback(() => {
|
||||
dispatch(gotoPage({ page: Math.max(page - 1, 1) }));
|
||||
}, [page, dispatch, gotoPage]);
|
||||
|
||||
const handleNextPagePress = useCallback(() => {
|
||||
dispatch(gotoPage({ page: Math.min(page + 1, totalPages) }));
|
||||
}, [page, totalPages, dispatch, gotoPage]);
|
||||
|
||||
const handleLastPagePress = useCallback(() => {
|
||||
dispatch(gotoPage({ page: totalPages }));
|
||||
}, [totalPages, dispatch, gotoPage]);
|
||||
|
||||
const handlePageSelect = useCallback(
|
||||
(page: number) => {
|
||||
dispatch(gotoPage({ page }));
|
||||
},
|
||||
[dispatch, gotoPage]
|
||||
);
|
||||
|
||||
return useMemo(() => {
|
||||
return {
|
||||
handleFirstPagePress,
|
||||
handlePreviousPagePress,
|
||||
handleNextPagePress,
|
||||
handleLastPagePress,
|
||||
handlePageSelect,
|
||||
};
|
||||
}, [
|
||||
handleFirstPagePress,
|
||||
handlePreviousPagePress,
|
||||
handleNextPagePress,
|
||||
handleLastPagePress,
|
||||
handlePageSelect,
|
||||
]);
|
||||
}
|
||||
|
||||
export default usePaging;
|
@ -0,0 +1,9 @@
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
function useCurrentPage() {
|
||||
const history = useHistory();
|
||||
|
||||
return history.action === 'POP';
|
||||
}
|
||||
|
||||
export default useCurrentPage;
|
@ -1,27 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import EditImportListExclusionModalContentConnector from './EditImportListExclusionModalContentConnector';
|
||||
|
||||
function EditImportListExclusionModal({ isOpen, onModalClose, ...otherProps }) {
|
||||
return (
|
||||
<Modal
|
||||
size={sizes.MEDIUM}
|
||||
isOpen={isOpen}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<EditImportListExclusionModalContentConnector
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
EditImportListExclusionModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default EditImportListExclusionModal;
|
@ -0,0 +1,41 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||
import EditImportListExclusionModalContent from './EditImportListExclusionModalContent';
|
||||
|
||||
interface EditImportListExclusionModalProps {
|
||||
id?: number;
|
||||
isOpen: boolean;
|
||||
onModalClose: () => void;
|
||||
onDeleteImportListExclusionPress?: () => void;
|
||||
}
|
||||
|
||||
function EditImportListExclusionModal(
|
||||
props: EditImportListExclusionModalProps
|
||||
) {
|
||||
const { isOpen, onModalClose, ...otherProps } = props;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const onModalClosePress = useCallback(() => {
|
||||
dispatch(
|
||||
clearPendingChanges({
|
||||
section: 'settings.importListExclusions',
|
||||
})
|
||||
);
|
||||
onModalClose();
|
||||
}, [dispatch, onModalClose]);
|
||||
|
||||
return (
|
||||
<Modal size={sizes.MEDIUM} isOpen={isOpen} onModalClose={onModalClosePress}>
|
||||
<EditImportListExclusionModalContent
|
||||
{...otherProps}
|
||||
onModalClose={onModalClosePress}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default EditImportListExclusionModal;
|
@ -1,43 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||
import EditImportListExclusionModal from './EditImportListExclusionModal';
|
||||
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
clearPendingChanges
|
||||
};
|
||||
|
||||
class EditImportListExclusionModalConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onModalClose = () => {
|
||||
this.props.clearPendingChanges({ section: 'settings.importListExclusions' });
|
||||
this.props.onModalClose();
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditImportListExclusionModal
|
||||
{...this.props}
|
||||
onModalClose={this.onModalClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditImportListExclusionModalConnector.propTypes = {
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
clearPendingChanges: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(EditImportListExclusionModalConnector);
|
@ -1,147 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
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 Button from 'Components/Link/Button';
|
||||
import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
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 { inputTypes, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditImportListExclusionModalContent.css';
|
||||
|
||||
function EditImportListExclusionModalContent(props) {
|
||||
const {
|
||||
id,
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
item,
|
||||
onInputChange,
|
||||
onSavePress,
|
||||
onModalClose,
|
||||
onDeleteImportListExclusionPress,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const {
|
||||
movieTitle = '',
|
||||
tmdbId,
|
||||
movieYear
|
||||
} = item;
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{id ? translate('EditImportListExclusion') : translate('AddImportListExclusion')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody className={styles.body}>
|
||||
{
|
||||
isFetching &&
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('AddImportListExclusionError')}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && !error &&
|
||||
<Form
|
||||
{...otherProps}
|
||||
>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('TMDBId')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="tmdbId"
|
||||
helpText={translate('TmdbIdHelpText')}
|
||||
{...tmdbId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('MovieTitle')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="movieTitle"
|
||||
helpText={translate('MovieTitleHelpText')}
|
||||
{...movieTitle}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('MovieYear')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="movieYear"
|
||||
helpText={translate('MovieYearHelpText')}
|
||||
{...movieYear}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
</Form>
|
||||
}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
{
|
||||
id &&
|
||||
<Button
|
||||
className={styles.deleteButton}
|
||||
kind={kinds.DANGER}
|
||||
onPress={onDeleteImportListExclusionPress}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</Button>
|
||||
}
|
||||
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Cancel')}
|
||||
</Button>
|
||||
|
||||
<SpinnerErrorButton
|
||||
isSpinning={isSaving}
|
||||
error={saveError}
|
||||
onPress={onSavePress}
|
||||
>
|
||||
{translate('Save')}
|
||||
</SpinnerErrorButton>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
|
||||
EditImportListExclusionModalContent.propTypes = {
|
||||
id: PropTypes.number,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
item: PropTypes.object.isRequired,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onSavePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
onDeleteImportListExclusionPress: PropTypes.func
|
||||
};
|
||||
|
||||
export default EditImportListExclusionModalContent;
|
@ -0,0 +1,201 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import AppState from 'App/State/AppState';
|
||||
import Alert from 'Components/Alert';
|
||||
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 Button from 'Components/Link/Button';
|
||||
import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
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 usePrevious from 'Helpers/Hooks/usePrevious';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import {
|
||||
saveImportListExclusion,
|
||||
setImportListExclusionValue,
|
||||
} from 'Store/Actions/settingsActions';
|
||||
import selectSettings from 'Store/Selectors/selectSettings';
|
||||
import ImportListExclusion from 'typings/ImportListExclusion';
|
||||
import { PendingSection } from 'typings/pending';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditImportListExclusionModalContent.css';
|
||||
|
||||
const newImportListExclusion = {
|
||||
movieTitle: '',
|
||||
movieYear: 0,
|
||||
tmdbId: 0,
|
||||
};
|
||||
|
||||
interface EditImportListExclusionModalContentProps {
|
||||
id?: number;
|
||||
onModalClose: () => void;
|
||||
onDeleteImportListExclusionPress?: () => void;
|
||||
}
|
||||
|
||||
function createImportListExclusionSelector(id?: number) {
|
||||
return createSelector(
|
||||
(state: AppState) => state.settings.importListExclusions,
|
||||
(importListExclusions) => {
|
||||
const { isFetching, error, isSaving, saveError, pendingChanges, items } =
|
||||
importListExclusions;
|
||||
|
||||
const mapping = id
|
||||
? items.find((i) => i.id === id)
|
||||
: newImportListExclusion;
|
||||
const settings = selectSettings(mapping, pendingChanges, saveError);
|
||||
|
||||
return {
|
||||
id,
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
item: settings.settings as PendingSection<ImportListExclusion>,
|
||||
...settings,
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function EditImportListExclusionModalContent(
|
||||
props: EditImportListExclusionModalContentProps
|
||||
) {
|
||||
const { id, onModalClose, onDeleteImportListExclusionPress } = props;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const dispatchSetImportListExclusionValue = (payload: {
|
||||
name: string;
|
||||
value: string | number;
|
||||
}) => {
|
||||
// @ts-expect-error 'setImportListExclusionValue' isn't typed yet
|
||||
dispatch(setImportListExclusionValue(payload));
|
||||
};
|
||||
|
||||
const { isFetching, isSaving, item, error, saveError, ...otherProps } =
|
||||
useSelector(createImportListExclusionSelector(props.id));
|
||||
const previousIsSaving = usePrevious(isSaving);
|
||||
|
||||
const { movieTitle, movieYear, tmdbId } = item;
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) {
|
||||
Object.keys(newImportListExclusion).forEach((name) => {
|
||||
dispatchSetImportListExclusionValue({
|
||||
name,
|
||||
value:
|
||||
newImportListExclusion[name as keyof typeof newImportListExclusion],
|
||||
});
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (previousIsSaving && !isSaving && !saveError) {
|
||||
onModalClose();
|
||||
}
|
||||
});
|
||||
|
||||
const onSavePress = useCallback(() => {
|
||||
dispatch(saveImportListExclusion({ id }));
|
||||
}, [dispatch, id]);
|
||||
|
||||
const onInputChange = useCallback(
|
||||
(payload: { name: string; value: string | number }) => {
|
||||
// @ts-expect-error 'setImportListExclusionValue' isn't typed yet
|
||||
dispatch(setImportListExclusionValue(payload));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{id
|
||||
? translate('EditImportListExclusion')
|
||||
: translate('AddImportListExclusion')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody className={styles.body}>
|
||||
{isFetching && <LoadingIndicator />}
|
||||
|
||||
{!isFetching && !!error && (
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('AddImportListExclusionError')}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{!isFetching && !error && (
|
||||
<Form {...otherProps}>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('TMDBId')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="tmdbId"
|
||||
helpText={translate('TmdbIdExcludeHelpText')}
|
||||
{...tmdbId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Title')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="movieTitle"
|
||||
helpText={translate('MovieTitleToExcludeHelpText')}
|
||||
{...movieTitle}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Year')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="movieYear"
|
||||
helpText={translate('MovieYearToExcludeHelpText')}
|
||||
{...movieYear}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
)}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
{id && (
|
||||
<Button
|
||||
className={styles.deleteButton}
|
||||
kind={kinds.DANGER}
|
||||
onPress={onDeleteImportListExclusionPress}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button onPress={onModalClose}>{translate('Cancel')}</Button>
|
||||
|
||||
<SpinnerErrorButton
|
||||
isSpinning={isSaving}
|
||||
error={saveError}
|
||||
onPress={onSavePress}
|
||||
>
|
||||
{translate('Save')}
|
||||
</SpinnerErrorButton>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default EditImportListExclusionModalContent;
|
@ -1,118 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { saveImportListExclusion, setImportListExclusionValue } from 'Store/Actions/settingsActions';
|
||||
import selectSettings from 'Store/Selectors/selectSettings';
|
||||
import EditImportListExclusionModalContent from './EditImportListExclusionModalContent';
|
||||
|
||||
const newImportListExclusion = {
|
||||
movieTitle: '',
|
||||
tmdbId: 0,
|
||||
movieYear: 0
|
||||
};
|
||||
|
||||
function createImportListExclusionSelector() {
|
||||
return createSelector(
|
||||
(state, { id }) => id,
|
||||
(state) => state.settings.importListExclusions,
|
||||
(id, importListExclusions) => {
|
||||
const {
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
pendingChanges,
|
||||
items
|
||||
} = importListExclusions;
|
||||
|
||||
const mapping = id ? items.find((i) => i.id === id) : newImportListExclusion;
|
||||
const settings = selectSettings(mapping, pendingChanges, saveError);
|
||||
|
||||
return {
|
||||
id,
|
||||
isFetching,
|
||||
error,
|
||||
isSaving,
|
||||
saveError,
|
||||
item: settings.settings,
|
||||
...settings
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createImportListExclusionSelector(),
|
||||
(importListExclusion) => {
|
||||
return {
|
||||
...importListExclusion
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setImportListExclusionValue,
|
||||
saveImportListExclusion
|
||||
};
|
||||
|
||||
class EditImportListExclusionModalContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.id) {
|
||||
Object.keys(newImportListExclusion).forEach((name) => {
|
||||
this.props.setImportListExclusionValue({
|
||||
name,
|
||||
value: newImportListExclusion[name]
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
|
||||
this.props.onModalClose();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onInputChange = ({ name, value }) => {
|
||||
this.props.setImportListExclusionValue({ name, value });
|
||||
};
|
||||
|
||||
onSavePress = () => {
|
||||
this.props.saveImportListExclusion({ id: this.props.id });
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EditImportListExclusionModalContent
|
||||
{...this.props}
|
||||
onSavePress={this.onSavePress}
|
||||
onInputChange={this.onInputChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditImportListExclusionModalContentConnector.propTypes = {
|
||||
id: PropTypes.number,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
saveError: PropTypes.object,
|
||||
item: PropTypes.object.isRequired,
|
||||
setImportListExclusionValue: PropTypes.func.isRequired,
|
||||
saveImportListExclusion: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(EditImportListExclusionModalContentConnector);
|
@ -1,26 +0,0 @@
|
||||
.importListExclusion {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
margin-bottom: 10px;
|
||||
height: 30px;
|
||||
border-bottom: 1px solid var(--borderColor);
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.movieTitle {
|
||||
@add-mixin truncate;
|
||||
|
||||
flex: 0 1 600px;
|
||||
}
|
||||
|
||||
.tmdbId,
|
||||
.movieYear {
|
||||
flex: 0 0 70px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 1 0 auto;
|
||||
padding-right: 10px;
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector';
|
||||
import styles from './ImportListExclusion.css';
|
||||
|
||||
class ImportListExclusion extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isEditImportListExclusionModalOpen: false,
|
||||
isDeleteImportListExclusionModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onEditImportListExclusionPress = () => {
|
||||
this.setState({ isEditImportListExclusionModalOpen: true });
|
||||
};
|
||||
|
||||
onEditImportListExclusionModalClose = () => {
|
||||
this.setState({ isEditImportListExclusionModalOpen: false });
|
||||
};
|
||||
|
||||
onDeleteImportListExclusionPress = () => {
|
||||
this.setState({
|
||||
isEditImportListExclusionModalOpen: false,
|
||||
isDeleteImportListExclusionModalOpen: true
|
||||
});
|
||||
};
|
||||
|
||||
onDeleteImportListExclusionModalClose = () => {
|
||||
this.setState({ isDeleteImportListExclusionModalOpen: false });
|
||||
};
|
||||
|
||||
onConfirmDeleteImportListExclusion = () => {
|
||||
this.props.onConfirmDeleteImportListExclusion(this.props.id);
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
id,
|
||||
movieTitle,
|
||||
tmdbId,
|
||||
movieYear
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.importListExclusion
|
||||
)}
|
||||
>
|
||||
<div className={styles.tmdbId}>{tmdbId}</div>
|
||||
<div className={styles.movieTitle} title={movieTitle}>{movieTitle}</div>
|
||||
<div className={styles.movieYear}>{movieYear}</div>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<Link
|
||||
onPress={this.onEditImportListExclusionPress}
|
||||
>
|
||||
<Icon name={icons.EDIT} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<EditImportListExclusionModalConnector
|
||||
id={id}
|
||||
isOpen={this.state.isEditImportListExclusionModalOpen}
|
||||
onModalClose={this.onEditImportListExclusionModalClose}
|
||||
onDeleteImportListExclusionPress={this.onDeleteImportListExclusionPress}
|
||||
/>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isDeleteImportListExclusionModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteImportListExclusion')}
|
||||
message={translate('DeleteImportListExclusionMessageText')}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteImportListExclusion}
|
||||
onCancel={this.onDeleteImportListExclusionModalClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportListExclusion.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
movieTitle: PropTypes.string.isRequired,
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
movieYear: PropTypes.number.isRequired,
|
||||
onConfirmDeleteImportListExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
ImportListExclusion.defaultProps = {
|
||||
// The drag preview will not connect the drag handle.
|
||||
connectDragSource: (node) => node
|
||||
};
|
||||
|
||||
export default ImportListExclusion;
|
@ -0,0 +1,6 @@
|
||||
.actions {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 35px;
|
||||
white-space: nowrap;
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import useModalOpenState from 'Helpers/Hooks/useModalOpenState';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import { deleteImportListExclusion } from 'Store/Actions/Settings/importListExclusions';
|
||||
import ImportListExclusion from 'typings/ImportListExclusion';
|
||||
import { SelectStateInputProps } from 'typings/props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditImportListExclusionModal from './EditImportListExclusionModal';
|
||||
import styles from './ImportListExclusionRow.css';
|
||||
|
||||
interface ImportListExclusionRowProps extends ImportListExclusion {
|
||||
isSelected: boolean;
|
||||
onSelectedChange: (options: SelectStateInputProps) => void;
|
||||
}
|
||||
|
||||
function ImportListExclusionRow(props: ImportListExclusionRowProps) {
|
||||
const { id, tmdbId, movieTitle, movieYear, isSelected, onSelectedChange } =
|
||||
props;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [
|
||||
isEditImportListExclusionModalOpen,
|
||||
setEditImportListExclusionModalOpen,
|
||||
setEditImportListExclusionModalClosed,
|
||||
] = useModalOpenState(false);
|
||||
|
||||
const [
|
||||
isDeleteImportListExclusionModalOpen,
|
||||
setDeleteImportListExclusionModalOpen,
|
||||
setDeleteImportListExclusionModalClosed,
|
||||
] = useModalOpenState(false);
|
||||
|
||||
const handleDeletePress = useCallback(() => {
|
||||
dispatch(deleteImportListExclusion({ id }));
|
||||
}, [id, dispatch]);
|
||||
|
||||
return (
|
||||
<TableRow>
|
||||
<TableSelectCell
|
||||
id={id}
|
||||
isSelected={isSelected}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
|
||||
<TableRowCell>{tmdbId}</TableRowCell>
|
||||
<TableRowCell>{movieTitle}</TableRowCell>
|
||||
<TableRowCell>{movieYear}</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
<IconButton
|
||||
name={icons.EDIT}
|
||||
onPress={setEditImportListExclusionModalOpen}
|
||||
/>
|
||||
</TableRowCell>
|
||||
|
||||
<EditImportListExclusionModal
|
||||
id={id}
|
||||
isOpen={isEditImportListExclusionModalOpen}
|
||||
onModalClose={setEditImportListExclusionModalClosed}
|
||||
onDeleteImportListExclusionPress={setDeleteImportListExclusionModalOpen}
|
||||
/>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={isDeleteImportListExclusionModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteImportListExclusion')}
|
||||
message={translate('DeleteImportListExclusionMessageText')}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={handleDeletePress}
|
||||
onCancel={setDeleteImportListExclusionModalClosed}
|
||||
/>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
export default ImportListExclusionRow;
|
@ -1,24 +1,6 @@
|
||||
.importListExclusionsHeader {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 0 1 600px;
|
||||
}
|
||||
|
||||
.tmdbId,
|
||||
.movieYear {
|
||||
flex: 0 0 70px;
|
||||
}
|
||||
|
||||
.addImportListExclusion {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.actions {
|
||||
composes: headerCell from '~Components/Table/TableHeaderCell.css';
|
||||
|
||||
.addButton {
|
||||
text-align: center;
|
||||
width: 35px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -1,12 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'addButton': string;
|
||||
'addImportListExclusion': string;
|
||||
'importListExclusionsHeader': string;
|
||||
'movieYear': string;
|
||||
'title': string;
|
||||
'tmdbId': string;
|
||||
'actions': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
|
@ -1,108 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector';
|
||||
import ImportListExclusion from './ImportListExclusion';
|
||||
import styles from './ImportListExclusions.css';
|
||||
|
||||
class ImportListExclusions extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isAddImportListExclusionModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onAddImportListExclusionPress = () => {
|
||||
this.setState({ isAddImportListExclusionModalOpen: true });
|
||||
};
|
||||
|
||||
onModalClose = () => {
|
||||
this.setState({ isAddImportListExclusionModalOpen: false });
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
items,
|
||||
onConfirmDeleteImportListExclusion,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldSet legend={translate('ImportListExclusions')}>
|
||||
<PageSectionContent
|
||||
errorMessage={translate('ImportListExclusionsLoadError')}
|
||||
{...otherProps}
|
||||
>
|
||||
<div className={styles.importListExclusionsHeader}>
|
||||
<div className={styles.tmdbId}>
|
||||
{translate('TMDBId')}
|
||||
</div>
|
||||
<div className={styles.title}>
|
||||
{translate('Title')}
|
||||
</div>
|
||||
<div className={styles.movieYear}>
|
||||
{translate('Year')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{
|
||||
items.map((item, index) => {
|
||||
return (
|
||||
<ImportListExclusion
|
||||
key={item.id}
|
||||
{...item}
|
||||
{...otherProps}
|
||||
index={index}
|
||||
onConfirmDeleteImportListExclusion={onConfirmDeleteImportListExclusion}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={styles.addImportListExclusion}>
|
||||
<Link
|
||||
className={styles.addButton}
|
||||
onPress={this.onAddImportListExclusionPress}
|
||||
>
|
||||
<Icon name={icons.ADD} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<EditImportListExclusionModalConnector
|
||||
isOpen={this.state.isAddImportListExclusionModalOpen}
|
||||
onModalClose={this.onModalClose}
|
||||
/>
|
||||
|
||||
</PageSectionContent>
|
||||
</FieldSet>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportListExclusions.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onConfirmDeleteImportListExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ImportListExclusions;
|
@ -0,0 +1,309 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import AppState from 'App/State/AppState';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import Column from 'Components/Table/Column';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import usePaging from 'Components/Table/usePaging';
|
||||
import useCurrentPage from 'Helpers/Hooks/useCurrentPage';
|
||||
import useModalOpenState from 'Helpers/Hooks/useModalOpenState';
|
||||
import usePrevious from 'Helpers/Hooks/usePrevious';
|
||||
import useSelectState from 'Helpers/Hooks/useSelectState';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import {
|
||||
bulkDeleteImportListExclusions,
|
||||
clearImportListExclusions,
|
||||
fetchImportListExclusions,
|
||||
gotoImportListExclusionPage,
|
||||
setImportListExclusionSort,
|
||||
setImportListExclusionTableOption,
|
||||
} from 'Store/Actions/Settings/importListExclusions';
|
||||
import { CheckInputChanged } from 'typings/inputs';
|
||||
import { SelectStateInputProps } from 'typings/props';
|
||||
import { TableOptionsChangePayload } from 'typings/Table';
|
||||
import {
|
||||
registerPagePopulator,
|
||||
unregisterPagePopulator,
|
||||
} from 'Utilities/pagePopulator';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import EditImportListExclusionModal from './EditImportListExclusionModal';
|
||||
import ImportListExclusionRow from './ImportListExclusionRow';
|
||||
import styles from './ImportListExclusions.css';
|
||||
|
||||
const COLUMNS: Column[] = [
|
||||
{
|
||||
name: 'tmdbid',
|
||||
label: () => translate('TMDBId'),
|
||||
isVisible: true,
|
||||
isSortable: true,
|
||||
},
|
||||
{
|
||||
name: 'movieTitle',
|
||||
label: () => translate('Title'),
|
||||
isVisible: true,
|
||||
isSortable: true,
|
||||
},
|
||||
{
|
||||
name: 'movieYear',
|
||||
label: () => translate('Year'),
|
||||
isVisible: true,
|
||||
isSortable: true,
|
||||
},
|
||||
{
|
||||
className: styles.actions,
|
||||
name: 'actions',
|
||||
label: '',
|
||||
isVisible: true,
|
||||
isSortable: false,
|
||||
},
|
||||
];
|
||||
|
||||
function createImportListExclusionsSelector() {
|
||||
return createSelector(
|
||||
(state: AppState) => state.settings.importListExclusions,
|
||||
(importListExclusions) => {
|
||||
return {
|
||||
...importListExclusions,
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function ImportListExclusions() {
|
||||
const requestCurrentPage = useCurrentPage();
|
||||
|
||||
const {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
items,
|
||||
pageSize,
|
||||
sortKey,
|
||||
error,
|
||||
sortDirection,
|
||||
page,
|
||||
totalPages,
|
||||
totalRecords,
|
||||
isDeleting,
|
||||
deleteError,
|
||||
} = useSelector(createImportListExclusionsSelector());
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [isConfirmDeleteModalOpen, setIsConfirmDeleteModalOpen] =
|
||||
useState(false);
|
||||
const previousIsDeleting = usePrevious(isDeleting);
|
||||
|
||||
const [selectState, setSelectState] = useSelectState();
|
||||
const { allSelected, allUnselected, selectedState } = selectState;
|
||||
|
||||
const selectedIds = useMemo(() => {
|
||||
return getSelectedIds(selectedState);
|
||||
}, [selectedState]);
|
||||
|
||||
const handleSelectAllChange = useCallback(
|
||||
({ value }: CheckInputChanged) => {
|
||||
setSelectState({ type: value ? 'selectAll' : 'unselectAll', items });
|
||||
},
|
||||
[items, setSelectState]
|
||||
);
|
||||
|
||||
const handleSelectedChange = useCallback(
|
||||
({ id, value, shiftKey = false }: SelectStateInputProps) => {
|
||||
setSelectState({
|
||||
type: 'toggleSelected',
|
||||
items,
|
||||
id,
|
||||
isSelected: value,
|
||||
shiftKey,
|
||||
});
|
||||
},
|
||||
[items, setSelectState]
|
||||
);
|
||||
|
||||
const handleDeleteSelectedPress = useCallback(() => {
|
||||
setIsConfirmDeleteModalOpen(true);
|
||||
}, [setIsConfirmDeleteModalOpen]);
|
||||
|
||||
const handleDeleteSelectedConfirmed = useCallback(() => {
|
||||
dispatch(bulkDeleteImportListExclusions({ ids: selectedIds }));
|
||||
setIsConfirmDeleteModalOpen(false);
|
||||
}, [selectedIds, setIsConfirmDeleteModalOpen, dispatch]);
|
||||
|
||||
const handleConfirmDeleteModalClose = useCallback(() => {
|
||||
setIsConfirmDeleteModalOpen(false);
|
||||
}, [setIsConfirmDeleteModalOpen]);
|
||||
|
||||
const {
|
||||
handleFirstPagePress,
|
||||
handlePreviousPagePress,
|
||||
handleNextPagePress,
|
||||
handleLastPagePress,
|
||||
handlePageSelect,
|
||||
} = usePaging({
|
||||
page,
|
||||
totalPages,
|
||||
gotoPage: gotoImportListExclusionPage,
|
||||
});
|
||||
|
||||
const handleSortPress = useCallback(
|
||||
(sortKey: { sortKey: string }) => {
|
||||
dispatch(setImportListExclusionSort({ sortKey }));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const handleTableOptionChange = useCallback(
|
||||
(payload: TableOptionsChangePayload) => {
|
||||
dispatch(setImportListExclusionTableOption(payload));
|
||||
|
||||
if (payload.pageSize) {
|
||||
dispatch(gotoImportListExclusionPage({ page: 1 }));
|
||||
}
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (requestCurrentPage) {
|
||||
dispatch(fetchImportListExclusions());
|
||||
} else {
|
||||
dispatch(gotoImportListExclusionPage({ page: 1 }));
|
||||
}
|
||||
|
||||
return () => {
|
||||
dispatch(clearImportListExclusions());
|
||||
};
|
||||
}, [requestCurrentPage, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const repopulate = () => {
|
||||
dispatch(fetchImportListExclusions());
|
||||
};
|
||||
|
||||
registerPagePopulator(repopulate);
|
||||
|
||||
return () => {
|
||||
unregisterPagePopulator(repopulate);
|
||||
};
|
||||
}, [dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (previousIsDeleting && !isDeleting && !deleteError) {
|
||||
setSelectState({ type: 'unselectAll', items });
|
||||
|
||||
dispatch(fetchImportListExclusions());
|
||||
}
|
||||
}, [
|
||||
previousIsDeleting,
|
||||
isDeleting,
|
||||
deleteError,
|
||||
items,
|
||||
dispatch,
|
||||
setSelectState,
|
||||
]);
|
||||
|
||||
const [
|
||||
isAddImportListExclusionModalOpen,
|
||||
setAddImportListExclusionModalOpen,
|
||||
setAddImportListExclusionModalClosed,
|
||||
] = useModalOpenState(false);
|
||||
|
||||
const isFetchingForFirstTime = isFetching && !isPopulated;
|
||||
|
||||
return (
|
||||
<FieldSet legend={translate('ImportListExclusions')}>
|
||||
<PageSectionContent
|
||||
errorMessage={translate('ImportListExclusionsLoadError')}
|
||||
isFetching={isFetchingForFirstTime}
|
||||
isPopulated={isPopulated}
|
||||
error={error}
|
||||
>
|
||||
<Table
|
||||
selectAll={true}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
columns={COLUMNS}
|
||||
canModifyColumns={false}
|
||||
pageSize={pageSize}
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onTableOptionChange={handleTableOptionChange}
|
||||
onSelectAllChange={handleSelectAllChange}
|
||||
onSortPress={handleSortPress}
|
||||
>
|
||||
<TableBody>
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<ImportListExclusionRow
|
||||
key={item.id}
|
||||
{...item}
|
||||
isSelected={selectedState[item.id] || false}
|
||||
onSelectedChange={handleSelectedChange}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
<TableRow>
|
||||
<TableRowCell colSpan={4}>
|
||||
<SpinnerButton
|
||||
kind={kinds.DANGER}
|
||||
isSpinning={isDeleting}
|
||||
isDisabled={!selectedIds.length}
|
||||
onPress={handleDeleteSelectedPress}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</SpinnerButton>
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell>
|
||||
<IconButton
|
||||
name={icons.ADD}
|
||||
onPress={setAddImportListExclusionModalOpen}
|
||||
/>
|
||||
</TableRowCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
<TablePager
|
||||
page={page}
|
||||
totalPages={totalPages}
|
||||
totalRecords={totalRecords}
|
||||
isFetching={isFetching}
|
||||
onFirstPagePress={handleFirstPagePress}
|
||||
onPreviousPagePress={handlePreviousPagePress}
|
||||
onNextPagePress={handleNextPagePress}
|
||||
onLastPagePress={handleLastPagePress}
|
||||
onPageSelect={handlePageSelect}
|
||||
/>
|
||||
|
||||
<EditImportListExclusionModal
|
||||
isOpen={isAddImportListExclusionModalOpen}
|
||||
onModalClose={setAddImportListExclusionModalClosed}
|
||||
/>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={isConfirmDeleteModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DeleteSelected')}
|
||||
message={translate('DeleteSelectedImportListExclusionsMessageText')}
|
||||
confirmLabel={translate('DeleteSelected')}
|
||||
onConfirm={handleDeleteSelectedConfirmed}
|
||||
onCancel={handleConfirmDeleteModalClose}
|
||||
/>
|
||||
</PageSectionContent>
|
||||
</FieldSet>
|
||||
);
|
||||
}
|
||||
|
||||
export default ImportListExclusions;
|
@ -1,59 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { deleteImportListExclusion, fetchImportListExclusions } from 'Store/Actions/settingsActions';
|
||||
import ImportListExclusions from './ImportListExclusions';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.settings.importListExclusions,
|
||||
(importListExclusions) => {
|
||||
return {
|
||||
...importListExclusions
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
fetchImportListExclusions,
|
||||
deleteImportListExclusion
|
||||
};
|
||||
|
||||
class ImportListExclusionsConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchImportListExclusions();
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onConfirmDeleteImportListExclusion = (id) => {
|
||||
this.props.deleteImportListExclusion({ id });
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ImportListExclusions
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
onConfirmDeleteImportListExclusion={this.onConfirmDeleteImportListExclusion}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportListExclusionsConnector.propTypes = {
|
||||
fetchImportListExclusions: PropTypes.func.isRequired,
|
||||
deleteImportListExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ImportListExclusionsConnector);
|
@ -0,0 +1,7 @@
|
||||
import ModelBase from 'App/ModelBase';
|
||||
|
||||
export default interface ImportListExclusion extends ModelBase {
|
||||
tmdbId: number;
|
||||
movieTitle: string;
|
||||
movieYear: number;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import Column from 'Components/Table/Column';
|
||||
|
||||
export interface TableOptionsChangePayload {
|
||||
pageSize?: number;
|
||||
columns: Column[];
|
||||
}
|
Loading…
Reference in new issue