From b6d9c73a179386806881ad282aea35e0a11753c6 Mon Sep 17 00:00:00 2001 From: The Dark <12370876+CheAle14@users.noreply.github.com> Date: Sun, 3 Mar 2024 05:19:02 +0000 Subject: [PATCH] New: Import list exclusion pagination and bulk removal (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) --- frontend/src/App/State/AppSectionState.ts | 4 + frontend/src/App/State/SettingsAppState.ts | 11 + frontend/src/Components/Table/Column.ts | 1 + frontend/src/Components/Table/Table.js | 5 +- frontend/src/Components/Table/usePaging.ts | 54 +++ frontend/src/Helpers/Hooks/useCurrentPage.ts | 9 + .../EditImportListExclusionModal.js | 27 -- .../EditImportListExclusionModal.tsx | 41 +++ .../EditImportListExclusionModalConnector.js | 43 --- .../EditImportListExclusionModalContent.js | 147 --------- .../EditImportListExclusionModalContent.tsx | 201 ++++++++++++ ...mportListExclusionModalContentConnector.js | 118 ------- .../ImportListExclusion.css | 26 -- .../ImportListExclusion.js | 115 ------- .../ImportListExclusionRow.css | 6 + ...s.d.ts => ImportListExclusionRow.css.d.ts} | 4 - .../ImportListExclusionRow.tsx | 83 +++++ .../ImportListExclusions.css | 26 +- .../ImportListExclusions.css.d.ts | 7 +- .../ImportListExclusions.js | 108 ------ .../ImportListExclusions.tsx | 309 ++++++++++++++++++ .../ImportListExclusionsConnector.js | 59 ---- .../ImportLists/ImportListSettings.js | 4 +- .../Actions/Settings/importListExclusions.js | 57 +++- frontend/src/Store/Actions/settingsActions.js | 3 +- .../createSettingsSectionSelector.ts | 51 ++- frontend/src/typings/ImportListExclusion.ts | 7 + frontend/src/typings/Table.ts | 6 + .../ImportListExclusionService.cs | 7 + src/NzbDrone.Core/Localization/Core/ar.json | 6 +- src/NzbDrone.Core/Localization/Core/bg.json | 6 +- src/NzbDrone.Core/Localization/Core/ca.json | 6 +- src/NzbDrone.Core/Localization/Core/cs.json | 6 +- src/NzbDrone.Core/Localization/Core/da.json | 6 +- src/NzbDrone.Core/Localization/Core/de.json | 6 +- src/NzbDrone.Core/Localization/Core/el.json | 6 +- src/NzbDrone.Core/Localization/Core/en.json | 8 +- src/NzbDrone.Core/Localization/Core/es.json | 6 +- src/NzbDrone.Core/Localization/Core/fi.json | 6 +- src/NzbDrone.Core/Localization/Core/fr.json | 6 +- src/NzbDrone.Core/Localization/Core/he.json | 6 +- src/NzbDrone.Core/Localization/Core/hi.json | 6 +- src/NzbDrone.Core/Localization/Core/hu.json | 6 +- src/NzbDrone.Core/Localization/Core/is.json | 6 +- src/NzbDrone.Core/Localization/Core/it.json | 6 +- src/NzbDrone.Core/Localization/Core/ja.json | 6 +- src/NzbDrone.Core/Localization/Core/ko.json | 6 +- src/NzbDrone.Core/Localization/Core/nl.json | 6 +- src/NzbDrone.Core/Localization/Core/pl.json | 6 +- src/NzbDrone.Core/Localization/Core/pt.json | 6 +- .../Localization/Core/pt_BR.json | 6 +- src/NzbDrone.Core/Localization/Core/ro.json | 6 +- src/NzbDrone.Core/Localization/Core/ru.json | 6 +- src/NzbDrone.Core/Localization/Core/sv.json | 6 +- src/NzbDrone.Core/Localization/Core/th.json | 6 +- src/NzbDrone.Core/Localization/Core/tr.json | 6 +- src/NzbDrone.Core/Localization/Core/uk.json | 6 +- src/NzbDrone.Core/Localization/Core/vi.json | 6 +- .../Localization/Core/zh_CN.json | 6 +- .../ImportListExclusionController.cs | 13 + 60 files changed, 930 insertions(+), 804 deletions(-) create mode 100644 frontend/src/Components/Table/usePaging.ts create mode 100644 frontend/src/Helpers/Hooks/useCurrentPage.ts delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.js create mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.tsx delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalConnector.js delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.js create mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.tsx delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContentConnector.js delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js create mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css rename frontend/src/Settings/ImportLists/ImportListExclusions/{ImportListExclusion.css.d.ts => ImportListExclusionRow.css.d.ts} (65%) create mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js create mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx delete mode 100644 frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js create mode 100644 frontend/src/typings/ImportListExclusion.ts create mode 100644 frontend/src/typings/Table.ts diff --git a/frontend/src/App/State/AppSectionState.ts b/frontend/src/App/State/AppSectionState.ts index cabc39b1c..a0bed6b2d 100644 --- a/frontend/src/App/State/AppSectionState.ts +++ b/frontend/src/App/State/AppSectionState.ts @@ -18,7 +18,10 @@ export interface AppSectionSaveState { } export interface PagedAppSectionState { + page: number; pageSize: number; + totalPages: number; + totalRecords?: number; } export interface AppSectionFilterState { @@ -38,6 +41,7 @@ export interface AppSectionItemState { isFetching: boolean; isPopulated: boolean; error: Error; + pendingChanges: Partial; item: T; } diff --git a/frontend/src/App/State/SettingsAppState.ts b/frontend/src/App/State/SettingsAppState.ts index a0bea0973..e4322db69 100644 --- a/frontend/src/App/State/SettingsAppState.ts +++ b/frontend/src/App/State/SettingsAppState.ts @@ -3,10 +3,12 @@ import AppSectionState, { AppSectionItemState, AppSectionSaveState, AppSectionSchemaState, + PagedAppSectionState, } from 'App/State/AppSectionState'; import Language from 'Language/Language'; import DownloadClient from 'typings/DownloadClient'; import ImportList from 'typings/ImportList'; +import ImportListExclusion from 'typings/ImportListExclusion'; import ImportListOptionsSettings from 'typings/ImportListOptionsSettings'; import Indexer from 'typings/Indexer'; import IndexerFlag from 'typings/IndexerFlag'; @@ -41,6 +43,14 @@ export interface ImportListOptionsSettingsAppState extends AppSectionItemState, AppSectionSaveState {} +export interface ImportListExclusionsSettingsAppState + extends AppSectionState, + AppSectionSaveState, + PagedAppSectionState, + AppSectionDeleteState { + pendingChanges: Partial; +} + export type IndexerFlagSettingsAppState = AppSectionState; export type LanguageSettingsAppState = AppSectionState; export type UiSettingsAppState = AppSectionItemState; @@ -48,6 +58,7 @@ export type UiSettingsAppState = AppSectionItemState; interface SettingsAppState { advancedSettings: boolean; downloadClients: DownloadClientAppState; + importListExclusions: ImportListExclusionsSettingsAppState; importListOptions: ImportListOptionsSettingsAppState; importLists: ImportListAppState; indexerFlags: IndexerFlagSettingsAppState; diff --git a/frontend/src/Components/Table/Column.ts b/frontend/src/Components/Table/Column.ts index 31a696df7..e49d67c44 100644 --- a/frontend/src/Components/Table/Column.ts +++ b/frontend/src/Components/Table/Column.ts @@ -5,6 +5,7 @@ type PropertyFunction = () => T; interface Column { name: string; label: string | PropertyFunction | React.ReactNode; + className?: string; columnLabel?: string; isSortable?: boolean; isVisible: boolean; diff --git a/frontend/src/Components/Table/Table.js b/frontend/src/Components/Table/Table.js index 8afbf9ea0..4c970e469 100644 --- a/frontend/src/Components/Table/Table.js +++ b/frontend/src/Components/Table/Table.js @@ -66,7 +66,9 @@ function Table(props) { columns.map((column) => { const { name, - isVisible + isVisible, + isSortable, + ...otherColumnProps } = column; if (!isVisible) { @@ -84,6 +86,7 @@ function Table(props) { name={name} isSortable={false} {...otherProps} + {...otherColumnProps} > 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; diff --git a/frontend/src/Helpers/Hooks/useCurrentPage.ts b/frontend/src/Helpers/Hooks/useCurrentPage.ts new file mode 100644 index 000000000..3caf66df2 --- /dev/null +++ b/frontend/src/Helpers/Hooks/useCurrentPage.ts @@ -0,0 +1,9 @@ +import { useHistory } from 'react-router-dom'; + +function useCurrentPage() { + const history = useHistory(); + + return history.action === 'POP'; +} + +export default useCurrentPage; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.js b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.js deleted file mode 100644 index 57a7b0e2d..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.js +++ /dev/null @@ -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 ( - - - - ); -} - -EditImportListExclusionModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditImportListExclusionModal; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.tsx b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.tsx new file mode 100644 index 000000000..b889a8105 --- /dev/null +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModal.tsx @@ -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 ( + + + + ); +} + +export default EditImportListExclusionModal; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalConnector.js b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalConnector.js deleted file mode 100644 index cd4338621..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalConnector.js +++ /dev/null @@ -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 ( - - ); - } -} - -EditImportListExclusionModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(mapStateToProps, mapDispatchToProps)(EditImportListExclusionModalConnector); diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.js b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.js deleted file mode 100644 index a430df34b..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.js +++ /dev/null @@ -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 ( - - - {id ? translate('EditImportListExclusion') : translate('AddImportListExclusion')} - - - - { - isFetching && - - } - - { - !isFetching && !!error && - - {translate('AddImportListExclusionError')} - - } - - { - !isFetching && !error && -
- - {translate('TMDBId')} - - - - - - {translate('MovieTitle')} - - - - - - {translate('MovieYear')} - - - - -
- } -
- - - { - id && - - } - - - - - {translate('Save')} - - -
- ); -} - -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; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.tsx b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.tsx new file mode 100644 index 000000000..d1aa0852d --- /dev/null +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContent.tsx @@ -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, + ...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 ( + + + {id + ? translate('EditImportListExclusion') + : translate('AddImportListExclusion')} + + + + {isFetching && } + + {!isFetching && !!error && ( + + {translate('AddImportListExclusionError')} + + )} + + {!isFetching && !error && ( +
+ + {translate('TMDBId')} + + + + + + {translate('Title')} + + + + + + {translate('Year')} + + + +
+ )} +
+ + + {id && ( + + )} + + + + + {translate('Save')} + + +
+ ); +} + +export default EditImportListExclusionModalContent; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContentConnector.js b/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContentConnector.js deleted file mode 100644 index 0e86d98fe..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/EditImportListExclusionModalContentConnector.js +++ /dev/null @@ -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 ( - - ); - } -} - -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); diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css deleted file mode 100644 index 571abb59b..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css +++ /dev/null @@ -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; -} diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js deleted file mode 100644 index 632258cf2..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js +++ /dev/null @@ -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 ( -
-
{tmdbId}
-
{movieTitle}
-
{movieYear}
- -
- - - -
- - - - -
- ); - } -} - -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; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css new file mode 100644 index 000000000..c154fa5a3 --- /dev/null +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css @@ -0,0 +1,6 @@ +.actions { + composes: cell from '~Components/Table/Cells/TableRowCell.css'; + + width: 35px; + white-space: nowrap; +} diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css.d.ts b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css.d.ts similarity index 65% rename from frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css.d.ts rename to frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css.d.ts index 7a3245d59..d8ea83dc1 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css.d.ts +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.css.d.ts @@ -2,10 +2,6 @@ // Please do not change this file! interface CssExports { 'actions': string; - 'importListExclusion': string; - 'movieTitle': string; - 'movieYear': string; - 'tmdbId': string; } export const cssExports: CssExports; export default cssExports; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx new file mode 100644 index 000000000..a03fcaa8f --- /dev/null +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx @@ -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 ( + + + + {tmdbId} + {movieTitle} + {movieYear} + + + + + + + + + + ); +} + +export default ImportListExclusionRow; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css index 8c397be9c..e213a1c11 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css @@ -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; } diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts index 3603c0092..d8ea83dc1 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts @@ -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; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js deleted file mode 100644 index 159981af4..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js +++ /dev/null @@ -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 ( -
- -
-
- {translate('TMDBId')} -
-
- {translate('Title')} -
-
- {translate('Year')} -
-
- -
- { - items.map((item, index) => { - return ( - - ); - }) - } -
- -
- - - -
- - - -
-
- ); - } -} - -ImportListExclusions.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteImportListExclusion: PropTypes.func.isRequired -}; - -export default ImportListExclusions; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx new file mode 100644 index 000000000..dc5545e59 --- /dev/null +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx @@ -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 ( +
+ + + + {items.map((item) => { + return ( + + ); + })} + + + + + {translate('Delete')} + + + + + + + + +
+ + + + + + +
+
+ ); +} + +export default ImportListExclusions; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js deleted file mode 100644 index 184788cec..000000000 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js +++ /dev/null @@ -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 ( - - ); - } -} - -ImportListExclusionsConnector.propTypes = { - fetchImportListExclusions: PropTypes.func.isRequired, - deleteImportListExclusion: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportListExclusionsConnector); diff --git a/frontend/src/Settings/ImportLists/ImportListSettings.js b/frontend/src/Settings/ImportLists/ImportListSettings.js index f7dabfc6b..f2641f43c 100644 --- a/frontend/src/Settings/ImportLists/ImportListSettings.js +++ b/frontend/src/Settings/ImportLists/ImportListSettings.js @@ -7,7 +7,7 @@ import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; import { icons } from 'Helpers/Props'; import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; import translate from 'Utilities/String/translate'; -import ImportListExclusionsConnector from './ImportListExclusions/ImportListExclusionsConnector'; +import ImportListExclusions from './ImportListExclusions/ImportListExclusions'; import ImportListsConnector from './ImportLists/ImportListsConnector'; import ManageImportListsModal from './ImportLists/Manage/ManageImportListsModal'; import ImportListOptions from './Options/ImportListOptions'; @@ -103,7 +103,7 @@ class ImportListSettings extends Component { onChildStateChange={this.onChildStateChange} /> - + { return { section, @@ -45,27 +59,52 @@ export default { isFetching: false, isPopulated: false, error: null, + pageSize: 20, items: [], isSaving: false, saveError: null, + isDeleting: false, + deleteError: null, pendingChanges: {} }, // // Action Handlers - actionHandlers: { - [FETCH_IMPORT_LIST_EXCLUSIONS]: createFetchHandler(section, '/exclusions'), - + actionHandlers: handleThunks({ + ...createServerSideCollectionHandlers( + section, + '/exclusions/paged', + fetchImportListExclusions, + { + [serverSideCollectionHandlers.FETCH]: FETCH_IMPORT_LIST_EXCLUSIONS, + [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_IMPORT_LIST_EXCLUSION_PAGE, + [serverSideCollectionHandlers.SORT]: SET_IMPORT_LIST_EXCLUSION_SORT + } + ), [SAVE_IMPORT_LIST_EXCLUSION]: createSaveProviderHandler(section, '/exclusions'), - [DELETE_IMPORT_LIST_EXCLUSION]: createRemoveItemHandler(section, '/exclusions') - }, + [DELETE_IMPORT_LIST_EXCLUSION]: createRemoveItemHandler(section, '/exclusions'), + [BULK_DELETE_IMPORT_LIST_EXCLUSIONS]: createBulkRemoveItemHandler(section, '/exclusions/bulk') + }), // // Reducers reducers: { - [SET_IMPORT_LIST_EXCLUSION_VALUE]: createSetSettingValueReducer(section) + [SET_IMPORT_LIST_EXCLUSION_VALUE]: createSetSettingValueReducer(section), + [SET_IMPORT_LIST_EXCLUSION_TABLE_OPTION]: createSetTableOptionReducer(section), + + [CLEAR_IMPORT_LIST_EXCLUSIONS]: createClearReducer(section, { + isFetching: false, + isPopulated: false, + error: null, + items: [], + isDeleting: false, + deleteError: null, + pendingChanges: {}, + totalPages: 0, + totalRecords: 0 + }) } }; diff --git a/frontend/src/Store/Actions/settingsActions.js b/frontend/src/Store/Actions/settingsActions.js index 72ac92a5d..f22abe809 100644 --- a/frontend/src/Store/Actions/settingsActions.js +++ b/frontend/src/Store/Actions/settingsActions.js @@ -94,7 +94,8 @@ export const defaultState = { }; export const persistState = [ - 'settings.advancedSettings' + 'settings.advancedSettings', + 'settings.importListExclusions.pageSize' ]; // diff --git a/frontend/src/Store/Selectors/createSettingsSectionSelector.ts b/frontend/src/Store/Selectors/createSettingsSectionSelector.ts index f43e4e59b..ad1e9cd6b 100644 --- a/frontend/src/Store/Selectors/createSettingsSectionSelector.ts +++ b/frontend/src/Store/Selectors/createSettingsSectionSelector.ts @@ -1,45 +1,44 @@ import { createSelector } from 'reselect'; -import AppSectionState, { - AppSectionItemState, -} from 'App/State/AppSectionState'; +import { AppSectionItemState } from 'App/State/AppSectionState'; import AppState from 'App/State/AppState'; +import SettingsAppState from 'App/State/SettingsAppState'; import selectSettings from 'Store/Selectors/selectSettings'; import { PendingSection } from 'typings/pending'; -type SettingNames = keyof Omit; -type GetSectionState = AppState['settings'][Name]; -type GetSettingsSectionItemType = - GetSectionState extends AppSectionItemState - ? R - : GetSectionState extends AppSectionState - ? R +type SectionsWithItemNames = { + [K in keyof SettingsAppState]: SettingsAppState[K] extends AppSectionItemState + ? K : never; +}[keyof SettingsAppState]; -type AppStateWithPending = { - item?: GetSettingsSectionItemType; - pendingChanges?: Partial>; - saveError?: Error; -} & GetSectionState; +type GetSectionState = + SettingsAppState[Name]; +type GetSettingsSectionItemType = + GetSectionState extends AppSectionItemState ? R : never; -function createSettingsSectionSelector( - section: Name -) { +function createSettingsSectionSelector< + Name extends SectionsWithItemNames, + T extends GetSettingsSectionItemType +>(section: Name) { return createSelector( (state: AppState) => state.settings[section], (sectionSettings) => { - const { item, pendingChanges, saveError, ...other } = - sectionSettings as AppStateWithPending; + const { item, pendingChanges, ...other } = sectionSettings; - const { settings, ...rest } = selectSettings( - item, - pendingChanges, - saveError - ); + const saveError = + 'saveError' in sectionSettings ? sectionSettings.saveError : undefined; + + const { + settings, + pendingChanges: selectedPendingChanges, + ...rest + } = selectSettings(item, pendingChanges, saveError); return { ...other, saveError, - settings: settings as PendingSection>, + settings: settings as PendingSection, + pendingChanges: selectedPendingChanges as Partial, ...rest, }; } diff --git a/frontend/src/typings/ImportListExclusion.ts b/frontend/src/typings/ImportListExclusion.ts new file mode 100644 index 000000000..5413de56e --- /dev/null +++ b/frontend/src/typings/ImportListExclusion.ts @@ -0,0 +1,7 @@ +import ModelBase from 'App/ModelBase'; + +export default interface ImportListExclusion extends ModelBase { + tmdbId: number; + movieTitle: string; + movieYear: number; +} diff --git a/frontend/src/typings/Table.ts b/frontend/src/typings/Table.ts new file mode 100644 index 000000000..4f99e2045 --- /dev/null +++ b/frontend/src/typings/Table.ts @@ -0,0 +1,6 @@ +import Column from 'Components/Table/Column'; + +export interface TableOptionsChangePayload { + pageSize?: number; + columns: Column[]; +} diff --git a/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportListExclusionService.cs b/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportListExclusionService.cs index 54781bf48..5251ddb5e 100644 --- a/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportListExclusionService.cs +++ b/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportListExclusionService.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Core.Datastore; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Movies.Events; @@ -11,6 +12,7 @@ namespace NzbDrone.Core.ImportLists.ImportExclusions ImportListExclusion Add(ImportListExclusion importListExclusion); List Add(List importListExclusions); List All(); + PagingSpec Paged(PagingSpec pagingSpec); bool IsMovieExcluded(int tmdbId); void Delete(int id); void Delete(List ids); @@ -78,6 +80,11 @@ namespace NzbDrone.Core.ImportLists.ImportExclusions return _repo.All().ToList(); } + public PagingSpec Paged(PagingSpec pagingSpec) + { + return _repo.GetPaged(pagingSpec); + } + public List AllExcludedTmdbIds() { return _repo.AllExcludedTmdbIds(); diff --git a/src/NzbDrone.Core/Localization/Core/ar.json b/src/NzbDrone.Core/Localization/Core/ar.json index 2bf10071b..2d98f89e6 100644 --- a/src/NzbDrone.Core/Localization/Core/ar.json +++ b/src/NzbDrone.Core/Localization/Core/ar.json @@ -111,7 +111,7 @@ "TorrentDelay": "تأخير السيل", "Tomorrow": "غدا", "Today": "اليوم", - "TmdbIdHelpText": "معرّف TMDb الخاص بالفيلم المراد استبعاده", + "TmdbIdExcludeHelpText": "معرّف TMDb الخاص بالفيلم المراد استبعاده", "TMDBId": "معرف TMDb", "TMDb": "TMDb", "Titles": "الألقاب", @@ -276,9 +276,9 @@ "MustNotContain": "يجب ألا يحتوي", "MustContain": "يجب أن يحتوي على", "MultiLanguage": "متعدد اللغات", - "MovieYearHelpText": "عام الفيلم المطلوب استبعاده", + "MovieYearToExcludeHelpText": "عام الفيلم المطلوب استبعاده", "MovieYear": "سنة الفيلم", - "MovieTitleHelpText": "عنوان الفيلم المراد استبعاده (يمكن أن يكون أي شيء ذي معنى)", + "MovieTitleToExcludeHelpText": "عنوان الفيلم المراد استبعاده (يمكن أن يكون أي شيء ذي معنى)", "MovieTitle": "عنوان الفيلم", "MoviesSelectedInterp": "تم تحديد {0} فيلم (أفلام)", "Movies": "أفلام", diff --git a/src/NzbDrone.Core/Localization/Core/bg.json b/src/NzbDrone.Core/Localization/Core/bg.json index 33697bf96..c5deb2852 100644 --- a/src/NzbDrone.Core/Localization/Core/bg.json +++ b/src/NzbDrone.Core/Localization/Core/bg.json @@ -572,7 +572,7 @@ "Title": "Заглавие", "Titles": "Заглавия", "TMDBId": "Идентификатор на TMDb", - "TmdbIdHelpText": "Идентификаторът на TMDb на филма за изключване", + "TmdbIdExcludeHelpText": "Идентификаторът на TMDb на филма за изключване", "Today": "Днес", "TorrentDelay": "Торент закъснение", "TorrentDelayHelpText": "Забавете за минути, за да изчакате, преди да вземете порой", @@ -883,9 +883,9 @@ "Movies": "Филми", "MoviesSelectedInterp": "{0} Избран / и филм / и", "MovieTitle": "Заглавие на филма", - "MovieTitleHelpText": "Заглавието на филма, който трябва да се изключи (може да бъде всичко смислено)", + "MovieTitleToExcludeHelpText": "Заглавието на филма, който трябва да се изключи (може да бъде всичко смислено)", "MovieYear": "Филмова година", - "MovieYearHelpText": "Годината на филма за изключване", + "MovieYearToExcludeHelpText": "Годината на филма за изключване", "MustContain": "Трябва да съдържа", "MustNotContain": "Не трябва да съдържа", "NamingSettings": "Настройки за именуване", diff --git a/src/NzbDrone.Core/Localization/Core/ca.json b/src/NzbDrone.Core/Localization/Core/ca.json index 6958af387..e74d06f06 100644 --- a/src/NzbDrone.Core/Localization/Core/ca.json +++ b/src/NzbDrone.Core/Localization/Core/ca.json @@ -99,9 +99,9 @@ "MovieFolderFormat": "Format de carpeta de pel·lícules", "MovieIndex": "Índex de pel·lícules", "MovieTitle": "Títol de la pel·lícula", - "MovieTitleHelpText": "El títol de la pel·lícula a excloure (pot ser qualsevol cosa amb sentit)", + "MovieTitleToExcludeHelpText": "El títol de la pel·lícula a excloure (pot ser qualsevol cosa amb sentit)", "MovieYear": "Any de la pel·lícula", - "MovieYearHelpText": "L'any de la pel·lícula a excloure", + "MovieYearToExcludeHelpText": "L'any de la pel·lícula a excloure", "NoAltTitle": "No hi ha títols alternatius.", "NoBackupsAreAvailable": "No hi ha còpies de seguretat disponibles", "NoChange": "Cap canvi", @@ -869,7 +869,7 @@ "Titles": "Títols", "TMDb": "TMDb", "TMDBId": "Identificador de TMDb", - "TmdbIdHelpText": "L'identificador de TMDb de la pel·lícula a excloure", + "TmdbIdExcludeHelpText": "L'identificador de TMDb de la pel·lícula a excloure", "TmdbVotes": "Vots de TMDb", "Today": "Avui", "Tomorrow": "Demà", diff --git a/src/NzbDrone.Core/Localization/Core/cs.json b/src/NzbDrone.Core/Localization/Core/cs.json index 6850c6594..8345f346c 100644 --- a/src/NzbDrone.Core/Localization/Core/cs.json +++ b/src/NzbDrone.Core/Localization/Core/cs.json @@ -376,9 +376,9 @@ "Movies": "Filmy", "MoviesSelectedInterp": "{0} Vybrané filmy", "MovieTitle": "Název filmu", - "MovieTitleHelpText": "Název filmu, který se má vyloučit (může mít cokoli smysluplného)", + "MovieTitleToExcludeHelpText": "Název filmu, který se má vyloučit (může mít cokoli smysluplného)", "MovieYear": "Filmový rok", - "MovieYearHelpText": "Rok filmu, který se má vyloučit", + "MovieYearToExcludeHelpText": "Rok filmu, který se má vyloučit", "MustContain": "Musí obsahovat", "MustNotContain": "Nesmí obsahovat", "NamingSettings": "Nastavení pojmenování", @@ -865,7 +865,7 @@ "Title": "Titul", "Titles": "Tituly", "TMDBId": "ID TMDb", - "TmdbIdHelpText": "ID TMDb filmu, které se má vyloučit", + "TmdbIdExcludeHelpText": "ID TMDb filmu, které se má vyloučit", "Today": "Dnes", "TorrentDelay": "Torrent Delay", "TorrentDelayHelpText": "Zpoždění v minutách čekání před popadnutím torrentu", diff --git a/src/NzbDrone.Core/Localization/Core/da.json b/src/NzbDrone.Core/Localization/Core/da.json index 92b0fd629..10bcb18d3 100644 --- a/src/NzbDrone.Core/Localization/Core/da.json +++ b/src/NzbDrone.Core/Localization/Core/da.json @@ -430,9 +430,9 @@ "MovieTitle": "Filmtitel", "EditDelayProfile": "Rediger forsinkelsesprofil", "Name": "Navn", - "MovieTitleHelpText": "Titlen på den film, der skal ekskluderes (kan være noget meningsfuldt)", + "MovieTitleToExcludeHelpText": "Titlen på den film, der skal ekskluderes (kan være noget meningsfuldt)", "MovieYear": "Filmår", - "MovieYearHelpText": "Året for filmen at udelukke", + "MovieYearToExcludeHelpText": "Året for filmen at udelukke", "MustContain": "Skal indeholde", "MustNotContain": "Må ikke indeholde", "NamingSettings": "Navngivningsindstillinger", @@ -845,7 +845,7 @@ "Title": "Titel", "Titles": "Titler", "TMDBId": "TMDb Id", - "TmdbIdHelpText": "TMDb-id for filmen, der skal ekskluderes", + "TmdbIdExcludeHelpText": "TMDb-id for filmen, der skal ekskluderes", "Today": "I dag", "TorrentDelay": "Torrentforsinkelse", "TorrentDelayHelpText": "Forsink i minutter, før du tager fat i en torrent", diff --git a/src/NzbDrone.Core/Localization/Core/de.json b/src/NzbDrone.Core/Localization/Core/de.json index 6834a3441..ddeec4f4e 100644 --- a/src/NzbDrone.Core/Localization/Core/de.json +++ b/src/NzbDrone.Core/Localization/Core/de.json @@ -413,9 +413,9 @@ "MovieID": "Film ID", "MovieInfoLanguageHelpTextWarning": "Seite muss neugeladen werden", "MovieIsDownloading": "Film ist am herunterladen", - "MovieTitleHelpText": "Der Titel des Filmes der augeschlossen werden soll", + "MovieTitleToExcludeHelpText": "Der Titel des Filmes der augeschlossen werden soll", "MovieYear": "Erscheinungsjahr", - "MovieYearHelpText": "Das Erscheinungsjahr des Filmes der ausgeschlossen werden soll", + "MovieYearToExcludeHelpText": "Das Erscheinungsjahr des Filmes der ausgeschlossen werden soll", "MustContain": "Muss beinhalten", "MustNotContain": "Darf nicht beinhalten", "NamingSettings": "Bennenungs Einstellungen", @@ -503,7 +503,7 @@ "Uptime": "Betriebszeit", "UrlBase": "URL-Basis", "TMDBId": "TMDb ID", - "TmdbIdHelpText": "Die TMDb ID für den Ausschluss", + "TmdbIdExcludeHelpText": "Die TMDb ID für den Ausschluss", "TorrentDelay": "Torrent-Verzögerung", "TorrentDelayHelpText": "Verzögerung in Minuten, bevor ein Torrent herunterladen wird", "Torrents": "Torrents", diff --git a/src/NzbDrone.Core/Localization/Core/el.json b/src/NzbDrone.Core/Localization/Core/el.json index 21c73ee36..edd509b00 100644 --- a/src/NzbDrone.Core/Localization/Core/el.json +++ b/src/NzbDrone.Core/Localization/Core/el.json @@ -372,9 +372,9 @@ "MoviesSelectedInterp": "{0} Επιλεγμένες ταινίες", "MovieTitle": "Τίτλος ταινίας", "Level": "Επίπεδο", - "MovieTitleHelpText": "Ο τίτλος της ταινίας προς εξαίρεση (μπορεί να είναι οτιδήποτε νόημα)", + "MovieTitleToExcludeHelpText": "Ο τίτλος της ταινίας προς εξαίρεση (μπορεί να είναι οτιδήποτε νόημα)", "MovieYear": "Έτος ταινίας", - "MovieYearHelpText": "Το έτος της ταινίας που αποκλείεται", + "MovieYearToExcludeHelpText": "Το έτος της ταινίας που αποκλείεται", "MustContain": "Πρέπει να περιέχει", "MustNotContain": "Δεν πρέπει να περιέχει", "NamingSettings": "Ρυθμίσεις ονομάτων", @@ -846,7 +846,7 @@ "Time": "χρόνος", "Title": "Τίτλος", "Titles": "Τίτλοι", - "TmdbIdHelpText": "Το αναγνωριστικό TMDb της ταινίας για εξαίρεση", + "TmdbIdExcludeHelpText": "Το αναγνωριστικό TMDb της ταινίας για εξαίρεση", "Today": "Σήμερα", "TorrentDelay": "Καθυστέρηση Torrent", "TorrentDelayHelpText": "Καθυστέρηση σε λίγα λεπτά για να περιμένετε πριν πιάσετε ένα χείμαρρο", diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 3b4f83551..cbf7530f1 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -336,8 +336,10 @@ "DeleteRestrictionHelpText": "Are you sure you want to delete this restriction?", "DeleteRootFolder": "Delete Root Folder", "DeleteRootFolderMessageText": "Are you sure you want to delete the root folder '{path}'?", + "DeleteSelected": "Delete Selected", "DeleteSelectedDownloadClients": "Delete Download Client(s)", "DeleteSelectedDownloadClientsMessageText": "Are you sure you want to delete {count} selected download client(s)?", + "DeleteSelectedImportListExclusionsMessageText": "Are you sure you want to delete the selected import list exclusions?", "DeleteSelectedImportLists": "Delete Import List(s)", "DeleteSelectedImportListsMessageText": "Are you sure you want to delete {count} selected import list(s)?", "DeleteSelectedIndexers": "Delete Indexer(s)", @@ -975,9 +977,9 @@ "MovieOnly": "Movie Only", "MovieSearchResultsLoadError": "Unable to load results for this movie search. Try again later", "MovieTitle": "Movie Title", - "MovieTitleHelpText": "The title of the movie to exclude (can be anything meaningful)", + "MovieTitleToExcludeHelpText": "The title of the movie to exclude (can be anything meaningful)", "MovieYear": "Movie Year", - "MovieYearHelpText": "The year of the movie to exclude", + "MovieYearToExcludeHelpText": "The year of the movie to exclude", "Movies": "Movies", "MoviesSelectedInterp": "{count} Movie(s) Selected", "MultiLanguage": "Multi-Language", @@ -1674,7 +1676,7 @@ "Timeleft": "Time Left", "Title": "Title", "Titles": "Titles", - "TmdbIdHelpText": "The TMDb Id of the movie to exclude", + "TmdbIdExcludeHelpText": "The TMDb Id of the movie to exclude", "TmdbRating": "TMDb Rating", "TmdbVotes": "TMDb Votes", "Today": "Today", diff --git a/src/NzbDrone.Core/Localization/Core/es.json b/src/NzbDrone.Core/Localization/Core/es.json index d7cd9138b..6ac142f3e 100644 --- a/src/NzbDrone.Core/Localization/Core/es.json +++ b/src/NzbDrone.Core/Localization/Core/es.json @@ -408,7 +408,7 @@ "Torrents": "Torrents", "TorrentDelayHelpText": "Retraso en minutos a esperar antes de capturar un torrent", "TorrentDelay": "Retraso de torrent", - "TmdbIdHelpText": "La Id de TMDb de la película a exluir", + "TmdbIdExcludeHelpText": "La Id de TMDb de la película a exluir", "TMDBId": "TMDb Id", "TestAllLists": "Probar todas las listas", "TestAllIndexers": "Probar todos los indexadores", @@ -507,9 +507,9 @@ "NamingSettings": "Opciones de nombrado", "MustNotContain": "No debe contener", "MustContain": "Debe contener", - "MovieYearHelpText": "Año de la película a excluir", + "MovieYearToExcludeHelpText": "Año de la película a excluir", "MovieYear": "Año de la Película", - "MovieTitleHelpText": "Ttítulo de la película a excluir (puedes ser cualquier cosa)", + "MovieTitleToExcludeHelpText": "Ttítulo de la película a excluir (puedes ser cualquier cosa)", "MovieIsDownloading": "Le película está descargando", "MovieInfoLanguageHelpTextWarning": "Recargar el Navegador", "MovieID": "ID de Película", diff --git a/src/NzbDrone.Core/Localization/Core/fi.json b/src/NzbDrone.Core/Localization/Core/fi.json index 2ade660ad..238580b09 100644 --- a/src/NzbDrone.Core/Localization/Core/fi.json +++ b/src/NzbDrone.Core/Localization/Core/fi.json @@ -320,7 +320,7 @@ "RelativePath": "Suhteellinen sijainti", "ReleaseRejected": "Vapautus hylätty", "MovieTitle": "Elokuvan nimi", - "MovieTitleHelpText": "Poissuljettava elokuvan nimi (voi olla mikä tahansa mielekäs)", + "MovieTitleToExcludeHelpText": "Poissuljettava elokuvan nimi (voi olla mikä tahansa mielekäs)", "MovieYear": "Elokuvan vuosi", "TestAllClients": "Lataustyökalujen testaus", "TestAllIndexers": "Tietolähteiden testaus", @@ -328,7 +328,7 @@ "AddRemotePathMapping": "Lisää etäsijainnin kohdistus", "Apply": "Käytä", "Analytics": "Analytiikka", - "MovieYearHelpText": "Elokuvan vuosi, joka suljetaan pois", + "MovieYearToExcludeHelpText": "Elokuvan vuosi, joka suljetaan pois", "Date": "Päiväys", "MustContain": "Täytyy sisältää", "MustNotContain": "Ei voi sisältää", @@ -849,7 +849,7 @@ "Title": "Nimike", "Titles": "Nimikkeet", "TMDBId": "TMDB ID", - "TmdbIdHelpText": "Ohitettavan elokuvan TMDB ID.", + "TmdbIdExcludeHelpText": "Ohitettavan elokuvan TMDB ID.", "Today": "Tänään", "TorrentDelay": "Torrent-viive", "TorrentDelayHelpText": "Minuuttiviive, joka odotetaan ennen julkaisun Torrent-kaappausta.", diff --git a/src/NzbDrone.Core/Localization/Core/fr.json b/src/NzbDrone.Core/Localization/Core/fr.json index 24af3896a..c9d338008 100644 --- a/src/NzbDrone.Core/Localization/Core/fr.json +++ b/src/NzbDrone.Core/Localization/Core/fr.json @@ -590,7 +590,7 @@ "UiLanguage": "Langue de l'IU", "TotalFileSize": "Taille totale des fichiers", "Torrents": "Torrents", - "TmdbIdHelpText": "L'ID TMDb du film à exclure", + "TmdbIdExcludeHelpText": "L'ID TMDb du film à exclure", "TMDBId": "Identifiant TMDb", "TestAllLists": "Tester toutes les listes", "TestAllIndexers": "Testez tous les indexeurs", @@ -718,10 +718,10 @@ "NetCore": ".NET", "NamingSettings": "Paramètres de dénomination", "MustNotContain": "Ne doit pas contenir", - "MovieYearHelpText": "L'année de film à exclure", + "MovieYearToExcludeHelpText": "L'année de film à exclure", "MustContain": "Doit contenir", "MovieYear": "Année du film", - "MovieTitleHelpText": "Le titre du film à exclure (peut être quelque chose de significatif)", + "MovieTitleToExcludeHelpText": "Le titre du film à exclure (peut être quelque chose de significatif)", "MovieIndexScrollTop": "Index des films : faire défiler vers le haut", "MovieIndexScrollBottom": "Index des films : faire défiler vers le bas", "MovieDetailsPreviousMovie": "Détails du film : Film Précédent", diff --git a/src/NzbDrone.Core/Localization/Core/he.json b/src/NzbDrone.Core/Localization/Core/he.json index d4df0fb7e..afb3b3353 100644 --- a/src/NzbDrone.Core/Localization/Core/he.json +++ b/src/NzbDrone.Core/Localization/Core/he.json @@ -9,7 +9,7 @@ "AvailabilityDelayHelpText": "משך הזמן לפני או אחרי התאריך הזמין לחיפוש הסרט", "BackupNow": "גיבוי עכשיו", "ChownGroupHelpText": "שם הקבוצה או ה- gid. השתמש ב- gid עבור מערכות קבצים מרוחקות.", - "MovieYearHelpText": "שנת הסרט לא הכללה", + "MovieYearToExcludeHelpText": "שנת הסרט לא הכללה", "ImportErrors": "ייבוא שגיאות", "IndexersSettingsSummary": "אינדקסים ומגבלות שחרור", "ReplaceWithDash": "החלף ב- Dash", @@ -84,7 +84,7 @@ "WhitelistedSubtitleTags": "תגיות כתוביות ברשימת ההיתרים", "MissingMonitoredAndConsideredAvailable": "חסר (מנוטר)", "ListTagsHelpText": "פריטי רשימת תגים יתווספו עם", - "MovieTitleHelpText": "כותרת הסרט לאי הכללה (יכולה להיות כל דבר בעל משמעות)", + "MovieTitleToExcludeHelpText": "כותרת הסרט לאי הכללה (יכולה להיות כל דבר בעל משמעות)", "MovieYear": "שנת הסרט", "DownloadPropersAndRepacksHelpTextCustomFormat": "השתמש ב'אל תעדיף 'כדי למיין לפי ציון פורמט מותאם אישית על פני Propers / Repacks", "AddListExclusionMovieHelpText": "מנע מלהוסיף סרט לרדאר על ידי רשימות", @@ -850,7 +850,7 @@ "Title": "כותרת", "Titles": "כותרות", "TMDBId": "מזהה TMDb", - "TmdbIdHelpText": "מזהה ה- TMDb של הסרט לא לכלול", + "TmdbIdExcludeHelpText": "מזהה ה- TMDb של הסרט לא לכלול", "Today": "היום", "TorrentDelay": "עיכוב סיקור", "TorrentDelayHelpText": "התעכב תוך דקות להמתין לפני שתופס סיקור", diff --git a/src/NzbDrone.Core/Localization/Core/hi.json b/src/NzbDrone.Core/Localization/Core/hi.json index 631774373..3800fb9e6 100644 --- a/src/NzbDrone.Core/Localization/Core/hi.json +++ b/src/NzbDrone.Core/Localization/Core/hi.json @@ -516,9 +516,9 @@ "Movies": "चलचित्र", "MoviesSelectedInterp": "{0} मूवी (s) चयनित", "MovieTitle": "चलचित्र शीर्षक", - "MovieTitleHelpText": "बहिष्कृत करने के लिए फिल्म का शीर्षक (सार्थक कुछ भी हो सकता है)", + "MovieTitleToExcludeHelpText": "बहिष्कृत करने के लिए फिल्म का शीर्षक (सार्थक कुछ भी हो सकता है)", "MovieYear": "मूवी वर्ष", - "MovieYearHelpText": "फिल्म को बाहर करने का वर्ष", + "MovieYearToExcludeHelpText": "फिल्म को बाहर करने का वर्ष", "MustContain": "शामिल होना चाहिए", "MustNotContain": "कंटेनर नहीं होना चाहिए", "NamingSettings": "नामकरण सेटिंग्स", @@ -888,7 +888,7 @@ "ThisCannotBeCancelled": "यह एक बार रद्द नहीं किया जा सकता है जब तक कि रेडर को फिर से शुरू किए बिना।", "Time": "समय", "TMDBId": "TMDb Id", - "TmdbIdHelpText": "बाहर करने के लिए फिल्म की TMDb Id", + "TmdbIdExcludeHelpText": "बाहर करने के लिए फिल्म की TMDb Id", "Today": "आज", "TorrentDelayTime": "धार विलंब: {0}", "Torrents": "टोरेंट", diff --git a/src/NzbDrone.Core/Localization/Core/hu.json b/src/NzbDrone.Core/Localization/Core/hu.json index 27cf6b12c..2520fc8e3 100644 --- a/src/NzbDrone.Core/Localization/Core/hu.json +++ b/src/NzbDrone.Core/Localization/Core/hu.json @@ -482,9 +482,9 @@ "Name": "Név", "MustNotContain": "Nem tartalmazhat", "MustContain": "Tartalmaznia kell", - "MovieYearHelpText": "A kizárandó film(ek) éve", + "MovieYearToExcludeHelpText": "A kizárandó film(ek) éve", "MovieYear": "Kiadási év", - "MovieTitleHelpText": "A kizárandó film címe (bármi értelmes lehet)", + "MovieTitleToExcludeHelpText": "A kizárandó film címe (bármi értelmes lehet)", "MovieTitle": "Filmcím", "MoviesSelectedInterp": "{0} Kiválasztott film(ek)", "Movies": "Filmek", @@ -619,7 +619,7 @@ "Torrents": "Torrentek", "TorrentDelayHelpText": "Percek késése, hogy várjon, mielőtt megragad egy torrentet", "TorrentDelay": "Torrent Késleltetés", - "TmdbIdHelpText": "A kizárandó film TMDb azonosítója", + "TmdbIdExcludeHelpText": "A kizárandó film TMDb azonosítója", "TMDBId": "TMDb azonosító", "Titles": "Címek", "Title": "Cím", diff --git a/src/NzbDrone.Core/Localization/Core/is.json b/src/NzbDrone.Core/Localization/Core/is.json index 84817e3f4..03c098540 100644 --- a/src/NzbDrone.Core/Localization/Core/is.json +++ b/src/NzbDrone.Core/Localization/Core/is.json @@ -342,7 +342,7 @@ "Calendar": "Dagatal", "MoviesSelectedInterp": "{0} Kvikmynd (ir) valdar", "MovieTitle": "Kvikmyndatitill", - "MovieTitleHelpText": "Titill myndarinnar til að útiloka (getur verið hvað sem er þýðingarmikill)", + "MovieTitleToExcludeHelpText": "Titill myndarinnar til að útiloka (getur verið hvað sem er þýðingarmikill)", "ClientPriority": "Forgangur viðskiptavinar", "DeleteCustomFormat": "Eyða sérsniðnu sniði", "DockerUpdater": "uppfærðu bryggjugáminn til að fá uppfærsluna", @@ -358,7 +358,7 @@ "InvalidFormat": "Ógilt snið", "Medium": "Miðlungs", "Minutes": "Fundargerð", - "MovieYearHelpText": "Ár kvikmyndarinnar til að útiloka", + "MovieYearToExcludeHelpText": "Ár kvikmyndarinnar til að útiloka", "Profiles": "Snið", "Reason": "Ástæða", "Released": "Sleppt", @@ -859,7 +859,7 @@ "Title": "Titill", "Titles": "Titlar", "TMDBId": "TMDb kt", - "TmdbIdHelpText": "TMDb auðkenni myndarinnar til að útiloka", + "TmdbIdExcludeHelpText": "TMDb auðkenni myndarinnar til að útiloka", "Today": "Í dag", "TorrentDelay": "Torrent Delay", "TorrentDelayHelpText": "Seinkaðu í nokkrar mínútur til að bíða áður en þú grípur strauminn", diff --git a/src/NzbDrone.Core/Localization/Core/it.json b/src/NzbDrone.Core/Localization/Core/it.json index a3b80d9d6..e9cc0497c 100644 --- a/src/NzbDrone.Core/Localization/Core/it.json +++ b/src/NzbDrone.Core/Localization/Core/it.json @@ -466,9 +466,9 @@ "NamingSettings": "Impostazioni di denominazione", "MustNotContain": "Non Deve Contenere", "MustContain": "Deve Contenere", - "MovieYearHelpText": "Anno del film da escludere", + "MovieYearToExcludeHelpText": "Anno del film da escludere", "MovieYear": "Anno del film", - "MovieTitleHelpText": "Titolo del Film da escludere (può essere qualunque cosa significativa)", + "MovieTitleToExcludeHelpText": "Titolo del Film da escludere (può essere qualunque cosa significativa)", "MoviesSelectedInterp": "{count} Film selezionato(i)", "MovieIsUnmonitored": "Il film è non monitorato", "MovieIsOnImportExclusionList": "Il Film è nella lista di esclusione dell'importazione", @@ -654,7 +654,7 @@ "Torrents": "Torrents", "TorrentDelayHelpText": "Ritardo in minuti da aspettare prima di prendere un torrent", "TorrentDelay": "Ritardo del torrent", - "TmdbIdHelpText": "Id di TMDb del film da escludere", + "TmdbIdExcludeHelpText": "Id di TMDb del film da escludere", "TMDBId": "ID di TMDb", "TimeFormat": "Formato Orario", "TestAllLists": "Testa tutte le liste", diff --git a/src/NzbDrone.Core/Localization/Core/ja.json b/src/NzbDrone.Core/Localization/Core/ja.json index 44d35a853..5651e818e 100644 --- a/src/NzbDrone.Core/Localization/Core/ja.json +++ b/src/NzbDrone.Core/Localization/Core/ja.json @@ -89,7 +89,7 @@ "AuthenticationMethodHelpText": "{appName}にアクセスするにはユーザー名とパスワードが必要です", "Component": "成分", "Proxy": "プロキシ", - "MovieTitleHelpText": "除外する映画のタイトル(意味のあるものであれば何でもかまいません)", + "MovieTitleToExcludeHelpText": "除外する映画のタイトル(意味のあるものであれば何でもかまいません)", "TestAllIndexers": "すべてのインデクサーをテストする", "AnalyseVideoFiles": "ビデオファイルを分析する", "AppDataDirectory": "AppDataディレクトリ", @@ -333,7 +333,7 @@ "Actions": "行動", "AddMovies": "映画を追加する", "IndexersSettingsSummary": "インデクサーとリリース制限", - "MovieYearHelpText": "除外する映画の年", + "MovieYearToExcludeHelpText": "除外する映画の年", "Age": "年齢", "NetCore": ".NET Core", "NoBackupsAreAvailable": "バックアップは利用できません", @@ -847,7 +847,7 @@ "Title": "題名", "Titles": "タイトル", "TMDBId": "TMDbID", - "TmdbIdHelpText": "除外する映画のTMDbID", + "TmdbIdExcludeHelpText": "除外する映画のTMDbID", "Today": "今日", "TorrentDelay": "トレント遅延", "Trace": "痕跡", diff --git a/src/NzbDrone.Core/Localization/Core/ko.json b/src/NzbDrone.Core/Localization/Core/ko.json index b50eacda2..36bc27fcc 100644 --- a/src/NzbDrone.Core/Localization/Core/ko.json +++ b/src/NzbDrone.Core/Localization/Core/ko.json @@ -328,7 +328,7 @@ "Movies": "영화", "MoviesSelectedInterp": "선택한 영화 {0} 개", "MovieTitle": "영화 제목", - "MovieTitleHelpText": "제외 할 영화 제목 (의미있는 것은 무엇이든 가능)", + "MovieTitleToExcludeHelpText": "제외 할 영화 제목 (의미있는 것은 무엇이든 가능)", "Actions": "동작", "Added": "추가됨", "AddNew": "새로 추가하기", @@ -337,7 +337,7 @@ "Agenda": "일정", "Failed": "실패한", "MovieYear": "영화 연도", - "MovieYearHelpText": "제외 할 영화 연도", + "MovieYearToExcludeHelpText": "제외 할 영화 연도", "MustContain": "포함해야 함", "MustNotContain": "포함해서는 안 됨", "NamingSettings": "이름 지정 설정", @@ -854,7 +854,7 @@ "Title": "제목", "Titles": "제목", "TMDBId": "TMDb ID", - "TmdbIdHelpText": "제외 할 영화의 TMDb ID", + "TmdbIdExcludeHelpText": "제외 할 영화의 TMDb ID", "Today": "오늘", "TorrentDelay": "급류 지연", "TorrentDelayHelpText": "급류를 잡기 전에 대기하는 데 몇 분이 걸립니다.", diff --git a/src/NzbDrone.Core/Localization/Core/nl.json b/src/NzbDrone.Core/Localization/Core/nl.json index 7648bdc9a..bf1551bd0 100644 --- a/src/NzbDrone.Core/Localization/Core/nl.json +++ b/src/NzbDrone.Core/Localization/Core/nl.json @@ -483,8 +483,8 @@ "MinimumCustomFormatScoreHelpText": "Minimum eigen formaat score toegelaten om te downloaden", "MinimumFreeSpaceHelpText": "Voorkom importeren indien de resulterende schijfruimte minder is dan deze hoeveelheid", "MovieIsOnImportExclusionList": "Film staat op de uitzonderingenlijst voor importeren", - "MovieTitleHelpText": "De titel van de uit te sluiten film (kan van alles zijn)", - "MovieYearHelpText": "Het jaar van de uit te sluiten film", + "MovieTitleToExcludeHelpText": "De titel van de uit te sluiten film (kan van alles zijn)", + "MovieYearToExcludeHelpText": "Het jaar van de uit te sluiten film", "NotificationTriggers": "Melding Reactiestarters", "OpenBrowserOnStart": "Open de browser bij het starten", "NoLimitForAnyRuntime": "Geen limiet voor eender welke speelduur", @@ -554,7 +554,7 @@ "TestAllClients": "Test Alle Downloaders", "TestAllLists": "Test Alle Lijsten", "TMDBId": "TMDb Id", - "TmdbIdHelpText": "De TMDb Id van de uit te sluiten film", + "TmdbIdExcludeHelpText": "De TMDb Id van de uit te sluiten film", "TorrentDelay": "Torrent Vertraging", "Torrents": "Torrents", "TotalFileSize": "Totale Bestandsgrootte", diff --git a/src/NzbDrone.Core/Localization/Core/pl.json b/src/NzbDrone.Core/Localization/Core/pl.json index 50d6efeff..48a73a0f4 100644 --- a/src/NzbDrone.Core/Localization/Core/pl.json +++ b/src/NzbDrone.Core/Localization/Core/pl.json @@ -336,9 +336,9 @@ "MovieIsUnmonitored": "Film jest niemonitorowany", "MoviesSelectedInterp": "Wybrane filmy: {0}", "MovieTitle": "Tytuł filmu", - "MovieTitleHelpText": "Tytuł filmu do wykluczenia (może być dowolny znaczący)", + "MovieTitleToExcludeHelpText": "Tytuł filmu do wykluczenia (może być dowolny znaczący)", "MovieYear": "Rok filmowy", - "MovieYearHelpText": "Rok filmu do wykluczenia", + "MovieYearToExcludeHelpText": "Rok filmu do wykluczenia", "MustContain": "Musi zawierać", "MustNotContain": "Nie może zawierać", "NamingSettings": "Ustawienia nazewnictwa", @@ -859,7 +859,7 @@ "Title": "Tytuł", "Titles": "Tytuły", "TMDBId": "Identyfikator TMDb", - "TmdbIdHelpText": "Identyfikator TMDb filmu do wykluczenia", + "TmdbIdExcludeHelpText": "Identyfikator TMDb filmu do wykluczenia", "Today": "Dzisiaj", "TorrentDelay": "Opóźnienie Torrenta", "TorrentDelayHelpText": "Opóźnienie w ciągu kilku minut, aby poczekać przed złapaniem torrenta", diff --git a/src/NzbDrone.Core/Localization/Core/pt.json b/src/NzbDrone.Core/Localization/Core/pt.json index 2059cd517..a7320aaed 100644 --- a/src/NzbDrone.Core/Localization/Core/pt.json +++ b/src/NzbDrone.Core/Localization/Core/pt.json @@ -335,9 +335,9 @@ "NamingSettings": "Definições de nomenclatura", "MustNotContain": "Não deve conter", "MustContain": "Deve conter", - "MovieYearHelpText": "Ano do filme a eliminar", + "MovieYearToExcludeHelpText": "Ano do filme a eliminar", "MovieYear": "Ano do filme", - "MovieTitleHelpText": "Título do filme a eliminar (pode ser qualquer palavra)", + "MovieTitleToExcludeHelpText": "Título do filme a eliminar (pode ser qualquer palavra)", "MovieIsDownloading": "Transferindo filme", "MovieInfoLanguageHelpTextWarning": "É preciso reiniciar o browser", "MovieID": "ID do filme", @@ -569,7 +569,7 @@ "ExtraFileExtensionsHelpTextsExamples": "Exemplos: \".sub, .nfo\" ou \"sub,nfo\"", "ExtraFileExtensionsHelpText": "Lista separada por vírgulas de ficheiros adicionais a importar (.nfo será importado como .nfo-orig)", "ExistingTag": "Etiqueta existente", - "TmdbIdHelpText": "ID do TMDb do filme a eliminar", + "TmdbIdExcludeHelpText": "ID do TMDb do filme a eliminar", "MovieExcludedFromAutomaticAdd": "Filme eliminado da adição automática", "MovieAlreadyExcluded": "Filme já eliminado", "ExcludeMovie": "Eliminar filme", diff --git a/src/NzbDrone.Core/Localization/Core/pt_BR.json b/src/NzbDrone.Core/Localization/Core/pt_BR.json index 593eb3b3a..4aca6ceb5 100644 --- a/src/NzbDrone.Core/Localization/Core/pt_BR.json +++ b/src/NzbDrone.Core/Localization/Core/pt_BR.json @@ -462,9 +462,9 @@ "About": "Sobre", "Analytics": "Análises", "Month": "Mês", - "MovieYearHelpText": "O ano do filme a excluir", + "MovieYearToExcludeHelpText": "O ano do filme a excluir", "MovieYear": "Ano do filme", - "MovieTitleHelpText": "O título do filme a excluir (pode ser qualquer coisa significativa)", + "MovieTitleToExcludeHelpText": "O título do filme a excluir (pode ser qualquer coisa significativa)", "MovieTitle": "Título do filme", "MoviesSelectedInterp": "{count} Filme(s) selecionado(s)", "Movies": "Filmes", @@ -764,7 +764,7 @@ "Ui": "IU", "Type": "Tipo", "Torrents": "Torrents", - "TmdbIdHelpText": "A ID do TMDb do filme a excluir", + "TmdbIdExcludeHelpText": "A ID do TMDb do filme a excluir", "TMDBId": "ID do TMDb", "TMDb": "TMDb", "SslCertPathHelpText": "Caminho para o arquivo pfx", diff --git a/src/NzbDrone.Core/Localization/Core/ro.json b/src/NzbDrone.Core/Localization/Core/ro.json index d29a6a1e1..400714b5a 100644 --- a/src/NzbDrone.Core/Localization/Core/ro.json +++ b/src/NzbDrone.Core/Localization/Core/ro.json @@ -519,12 +519,12 @@ "BranchUpdate": "Sucursală de utilizat pentru actualizarea {appName}", "BranchUpdateMechanism": "Ramură utilizată de mecanismul extern de actualizare", "BypassProxyForLocalAddresses": "Nu folosiți Proxy pentru adrese locale", - "MovieTitleHelpText": "Titlul filmului de exclus (poate avea orice sens)", + "MovieTitleToExcludeHelpText": "Titlul filmului de exclus (poate avea orice sens)", "Local": "Local", "MovieYear": "Anul filmului", "RecyclingBinCleanup": "Curățarea coșului de reciclare", "RefreshMovie": "Reîmprospătați filmul", - "MovieYearHelpText": "Anul filmului de exclus", + "MovieYearToExcludeHelpText": "Anul filmului de exclus", "MustContain": "Trebuie sa contina", "MustNotContain": "Nu trebuie să conțină", "NamingSettings": "Setări de denumire", @@ -877,7 +877,7 @@ "TagIsNotUsedAndCanBeDeleted": "Eticheta nu este utilizată și poate fi ștearsă", "ICalTagsMoviesHelpText": "Se aplică filmelor cu cel puțin o etichetă potrivită", "TMDBId": "Cod TMDb", - "TmdbIdHelpText": "Codul TMDb al filmului de exclus", + "TmdbIdExcludeHelpText": "Codul TMDb al filmului de exclus", "Today": "Astăzi", "TorrentDelay": "Întârziere Torrent", "TorrentDelayTime": "Întârziere Torrent: {0}", diff --git a/src/NzbDrone.Core/Localization/Core/ru.json b/src/NzbDrone.Core/Localization/Core/ru.json index 12248740d..5c52ab228 100644 --- a/src/NzbDrone.Core/Localization/Core/ru.json +++ b/src/NzbDrone.Core/Localization/Core/ru.json @@ -490,9 +490,9 @@ "MustNotContain": "Не должен содержать", "MustContain": "Должен содержать", "MultiLanguage": "Многоязычный", - "MovieYearHelpText": "Год фильма для исключений", + "MovieYearToExcludeHelpText": "Год фильма для исключений", "MovieYear": "Год фильма", - "MovieTitleHelpText": "Название фильма для исключения (может быть любым)", + "MovieTitleToExcludeHelpText": "Название фильма для исключения (может быть любым)", "MovieTitle": "Название фильма", "MoviesSelectedInterp": "{count} фильм(ов) выбрано", "Movies": "Фильмы", @@ -771,7 +771,7 @@ "TorrentDelay": "Задержка торрента", "Tomorrow": "Завтра", "Today": "Сегодня", - "TmdbIdHelpText": "Идентификатор TMDb фильма, который нужно исключить", + "TmdbIdExcludeHelpText": "Идентификатор TMDb фильма, который нужно исключить", "TMDBId": "TMDb идентификатор", "TMDb": "TMDb", "SearchAll": "Искать все", diff --git a/src/NzbDrone.Core/Localization/Core/sv.json b/src/NzbDrone.Core/Localization/Core/sv.json index 6ec3b0a1d..c24f55aa2 100644 --- a/src/NzbDrone.Core/Localization/Core/sv.json +++ b/src/NzbDrone.Core/Localization/Core/sv.json @@ -709,9 +709,9 @@ "DatabaseMigration": "DB Migration", "ImportExtraFiles": "Importera extra filer", "ImportExtraFilesMovieHelpText": "Importera matchande extrafiler (undertexter, nfo, etc) efter import av en filmfil", - "MovieTitleHelpText": "Filmens titel att utesluta (kan vara något meningsfullt)", + "MovieTitleToExcludeHelpText": "Filmens titel att utesluta (kan vara något meningsfullt)", "MinimumCustomFormatScoreHelpText": "Lägsta möjliga anpassade formatpoäng tillåtet att ladda ner", - "MovieYearHelpText": "Året för filmen att utesluta", + "MovieYearToExcludeHelpText": "Året för filmen att utesluta", "ProxyType": "Proxy-typ", "NamingSettings": "Namninställningar", "LastDuration": "lastDuration", @@ -899,7 +899,7 @@ "TheLogLevelDefault": "Loggnivån är som standard 'Info' och kan ändras i", "ThisCannotBeCancelled": "Detta kan inte avbrytas en gång startat utan att {appName} startas om.", "TMDBId": "TMDb-id", - "TmdbIdHelpText": "TMDb-id för filmen att utesluta", + "TmdbIdExcludeHelpText": "TMDb-id för filmen att utesluta", "TorrentDelay": "Torrentfördröjning", "TorrentDelayHelpText": "Fördröja på några minuter för att vänta innan du tar en torrent", "TorrentDelayTime": "Torrentfördröjning: {0}", diff --git a/src/NzbDrone.Core/Localization/Core/th.json b/src/NzbDrone.Core/Localization/Core/th.json index 265bff871..63993aeef 100644 --- a/src/NzbDrone.Core/Localization/Core/th.json +++ b/src/NzbDrone.Core/Localization/Core/th.json @@ -169,7 +169,7 @@ "TagsSettingsSummary": "ดูแท็กทั้งหมดและวิธีการใช้งาน แท็กที่ไม่ได้ใช้สามารถลบออกได้", "TheLogLevelDefault": "ระดับการบันทึกมีค่าเริ่มต้นเป็น \"ข้อมูล\" และสามารถเปลี่ยนแปลงได้", "Titles": "ชื่อเรื่อง", - "TmdbIdHelpText": "TMDb Id ของภาพยนตร์ที่จะยกเว้น", + "TmdbIdExcludeHelpText": "TMDb Id ของภาพยนตร์ที่จะยกเว้น", "TorrentsDisabled": "Torrents ถูกปิดใช้งาน", "UiLanguageHelpText": "ภาษาที่ {appName} จะใช้สำหรับ UI", "UiSettingsSummary": "ตัวเลือกปฏิทินวันที่และสีบกพร่อง", @@ -442,9 +442,9 @@ "Movies": "ภาพยนตร์", "MoviesSelectedInterp": "{0} ภาพยนตร์ที่เลือก", "MovieTitle": "ชื่อหนัง", - "MovieTitleHelpText": "ชื่อของภาพยนตร์ที่จะไม่รวม (อาจมีความหมายอะไรก็ได้)", + "MovieTitleToExcludeHelpText": "ชื่อของภาพยนตร์ที่จะไม่รวม (อาจมีความหมายอะไรก็ได้)", "MovieYear": "ปีภาพยนตร์", - "MovieYearHelpText": "ปีของภาพยนตร์ที่จะไม่รวม", + "MovieYearToExcludeHelpText": "ปีของภาพยนตร์ที่จะไม่รวม", "MustContain": "ต้องมี", "MustNotContain": "ต้องไม่มี", "NamingSettings": "การตั้งชื่อการตั้งค่า", diff --git a/src/NzbDrone.Core/Localization/Core/tr.json b/src/NzbDrone.Core/Localization/Core/tr.json index 049af4c10..1d1dd96b9 100644 --- a/src/NzbDrone.Core/Localization/Core/tr.json +++ b/src/NzbDrone.Core/Localization/Core/tr.json @@ -299,7 +299,7 @@ "ThisCannotBeCancelled": "Bu, {appName} yeniden başlatılmadan başlatıldıktan sonra iptal edilemez.", "Title": "Başlık", "TMDBId": "TMDb Kimliği", - "TmdbIdHelpText": "Hariç tutulacak filmin TMDb Kimliği", + "TmdbIdExcludeHelpText": "Hariç tutulacak filmin TMDb Kimliği", "Today": "Bugün", "TorrentDelay": "Torrent Gecikmesi", "TorrentDelayHelpText": "Bir torrent almadan önce beklemek için dakikalar içinde gecikme", @@ -571,9 +571,9 @@ "MovieIsDownloading": "Film indiriliyor", "MovieIsUnmonitored": "Film takip edilmiyor", "MoviesSelectedInterp": "{count} Film Seçildi", - "MovieTitleHelpText": "Hariç tutulacak filmin başlığı (anlamlı herhangi bir şey olabilir)", + "MovieTitleToExcludeHelpText": "Hariç tutulacak filmin başlığı (anlamlı herhangi bir şey olabilir)", "MovieYear": "Film Yılı", - "MovieYearHelpText": "Hariç tutulacak film yılı", + "MovieYearToExcludeHelpText": "Hariç tutulacak film yılı", "PendingChangesDiscardChanges": "Değişiklikleri atın ve ayrıl", "PreferredSize": "Tercih Edilen Boyut", "Proper": "Uygun", diff --git a/src/NzbDrone.Core/Localization/Core/uk.json b/src/NzbDrone.Core/Localization/Core/uk.json index d037c249c..e044ec9c8 100644 --- a/src/NzbDrone.Core/Localization/Core/uk.json +++ b/src/NzbDrone.Core/Localization/Core/uk.json @@ -871,7 +871,7 @@ "Timeleft": "Час залишився", "Title": "Назва", "Titles": "Назви", - "TmdbIdHelpText": "Ідентифікатор TMDb фільму, який потрібно виключити", + "TmdbIdExcludeHelpText": "Ідентифікатор TMDb фільму, який потрібно виключити", "TmdbRating": "Рейтинг TMDb", "TmdbVotes": "Голоси TMDb", "TorrentDelayTime": "Затримка торрента: {0}", @@ -941,9 +941,9 @@ "InstallLatest": "Встановити останній", "MegabytesPerMinute": "Мегабайт за хвилину", "Message": "Повідомлення", - "MovieTitleHelpText": "Назва фільму, який потрібно виключити (може бути будь-яким значущим)", + "MovieTitleToExcludeHelpText": "Назва фільму, який потрібно виключити (може бути будь-яким значущим)", "MovieYear": "Фільм рік", - "MovieYearHelpText": "Рік фільму виключити", + "MovieYearToExcludeHelpText": "Рік фільму виключити", "NegateHelpText": "Якщо позначено, настроюваний формат не застосовуватиметься, якщо ця умова {0} збігається.", "Never": "Ніколи", "New": "Новий", diff --git a/src/NzbDrone.Core/Localization/Core/vi.json b/src/NzbDrone.Core/Localization/Core/vi.json index e25f06bfc..c07879b6e 100644 --- a/src/NzbDrone.Core/Localization/Core/vi.json +++ b/src/NzbDrone.Core/Localization/Core/vi.json @@ -469,9 +469,9 @@ "AddMovies": "Thêm phim", "MoviesSelectedInterp": "{0} Phim đã chọn", "MovieTitle": "Tên phim", - "MovieTitleHelpText": "Tiêu đề của bộ phim cần loại trừ (có thể là bất kỳ điều gì có ý nghĩa)", + "MovieTitleToExcludeHelpText": "Tiêu đề của bộ phim cần loại trừ (có thể là bất kỳ điều gì có ý nghĩa)", "MovieYear": "Năm phim", - "MovieYearHelpText": "Năm của bộ phim để loại trừ", + "MovieYearToExcludeHelpText": "Năm của bộ phim để loại trừ", "MustContain": "Phải chứa", "AddNewTmdbIdMessage": "Bạn cũng có thể tìm kiếm bằng cách sử dụng TMDb Id của một bộ phim. ví dụ. 'tmdb: 71663'", "Indexer": "Người lập chỉ mục", @@ -886,7 +886,7 @@ "Time": "Thời gian", "Title": "Tiêu đề", "TMDBId": "Id TMDb", - "TmdbIdHelpText": "Id TMDb của phim để loại trừ", + "TmdbIdExcludeHelpText": "Id TMDb của phim để loại trừ", "TorrentDelayTime": "Độ trễ Torrent: {0}", "Torrents": "Torrents", "Trailer": "Giới thiệu tóm tắt", diff --git a/src/NzbDrone.Core/Localization/Core/zh_CN.json b/src/NzbDrone.Core/Localization/Core/zh_CN.json index 5a740cd08..f8899441c 100644 --- a/src/NzbDrone.Core/Localization/Core/zh_CN.json +++ b/src/NzbDrone.Core/Localization/Core/zh_CN.json @@ -837,7 +837,7 @@ "TagsSettingsSummary": "显示全部标签和标签使用情况,可删除未使用的标签", "TMDb": "TMDb", "TMDBId": "TMDb ID", - "TmdbIdHelpText": "排除电影的TMDb ID", + "TmdbIdExcludeHelpText": "排除电影的TMDb ID", "TorrentDelay": "Torrent延时", "TorrentDelayTime": "Torrent延时:{0}", "Torrents": "种子", @@ -901,8 +901,8 @@ "NextExecution": "接下来执行", "New": "新的", "NegateHelpText": "如勾选,当条件 {0} 满足时不会应用自定义格式。", - "MovieYearHelpText": "排除的电影的年份", - "MovieTitleHelpText": "要排除的电影标题(可以是任何字段)", + "MovieYearToExcludeHelpText": "排除的电影的年份", + "MovieTitleToExcludeHelpText": "要排除的电影标题(可以是任何字段)", "MovieIsRecommend": "影片是根据最近添加的推荐", "MovieIndexScrollTop": "影片索引:滚动到顶部", "MovieIndexScrollBottom": "影片索引:滚动到底部", diff --git a/src/Radarr.Api.V3/ImportLists/ImportListExclusionController.cs b/src/Radarr.Api.V3/ImportLists/ImportListExclusionController.cs index 409480831..976b537e4 100644 --- a/src/Radarr.Api.V3/ImportLists/ImportListExclusionController.cs +++ b/src/Radarr.Api.V3/ImportLists/ImportListExclusionController.cs @@ -1,9 +1,11 @@ +using System; using System.Collections.Generic; using System.Linq; using FluentValidation; using Microsoft.AspNetCore.Mvc; using NzbDrone.Core.ImportLists.ImportExclusions; using Radarr.Http; +using Radarr.Http.Extensions; using Radarr.Http.REST; using Radarr.Http.REST.Attributes; @@ -25,6 +27,7 @@ namespace Radarr.Api.V3.ImportLists [HttpGet] [Produces("application/json")] + [Obsolete("Deprecated")] public List GetImportListExclusions() { return _importListExclusionService.All().ToResource(); @@ -35,6 +38,16 @@ namespace Radarr.Api.V3.ImportLists return _importListExclusionService.Get(id).ToResource(); } + [HttpGet("paged")] + [Produces("application/json")] + public PagingResource GetImportListExclusionsPaged([FromQuery] PagingRequestResource paging) + { + var pagingResource = new PagingResource(paging); + var pageSpec = pagingResource.MapToPagingSpec(); + + return pageSpec.ApplyToPage(_importListExclusionService.Paged, ImportListExclusionResourceMapper.ToResource); + } + [RestPostById] [Consumes("application/json")] public ActionResult AddImportListExclusion([FromBody] ImportListExclusionResource resource)