diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css index 661d8d36d..4fc337418 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css @@ -13,12 +13,9 @@ flex: 0 0 70px; } -.addImportExclusion { +.footerButtons { display: flex; justify-content: flex-end; padding-right: 10px; -} - -.addButton { - text-align: center; + gap: 10px; } diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts index 54deeeee7..94746bc07 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts @@ -1,8 +1,7 @@ // This file is automatically generated. // Please do not change this file! interface CssExports { - 'addButton': string; - 'addImportExclusion': string; + 'footerButtons': string; 'importListExclusionsHeader': string; 'movieYear': string; 'title': string; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js index f1ca666fe..94dddd670 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js @@ -3,8 +3,9 @@ import React, { Component } from 'react'; import FieldSet from 'Components/FieldSet'; import Icon from 'Components/Icon'; import Link from 'Components/Link/Link'; +import ConfirmModal from 'Components/Modal/ConfirmModal'; import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; +import { icons, kinds } from 'Helpers/Props'; import translate from 'Utilities/String/translate'; import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector'; import ImportListExclusion from './ImportListExclusion'; @@ -19,7 +20,8 @@ class ImportListExclusions extends Component { super(props, context); this.state = { - isAddImportExclusionModalOpen: false + isAddImportExclusionModalOpen: false, + isPurgeImportExclusionModalOpen: false }; } @@ -34,6 +36,19 @@ class ImportListExclusions extends Component { this.setState({ isAddImportExclusionModalOpen: false }); }; + onPurgeImportExclusionPress = () => { + this.setState({ isPurgeImportExclusionModalOpen: true }); + }; + + onPurgeImportExclusionModalClose = () => { + this.setState({ isPurgeImportExclusionModalOpen: false }); + }; + + onConfirmPurgeImportExclusions = () => { + this.props.onConfirmPurgeImportExclusions(); + this.onPurgeImportExclusionModalClose(); + }; + // // Render @@ -78,7 +93,14 @@ class ImportListExclusions extends Component { } -
+
+ + + + + ); @@ -102,7 +133,8 @@ ImportListExclusions.propTypes = { isFetching: PropTypes.bool.isRequired, error: PropTypes.object, items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteImportExclusion: PropTypes.func.isRequired + onConfirmDeleteImportExclusion: PropTypes.func.isRequired, + onConfirmPurgeImportExclusions: PropTypes.func.isRequired }; export default ImportListExclusions; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js index ffb3d1f53..6b91b6e25 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionsConnector.js @@ -2,7 +2,11 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import { deleteImportExclusion, fetchImportExclusions } from 'Store/Actions/settingsActions'; +import { + deleteImportExclusion, + fetchImportExclusions, + purgeImportExclusions +} from 'Store/Actions/settingsActions'; import ImportListExclusions from './ImportListExclusions'; function createMapStateToProps() { @@ -18,11 +22,11 @@ function createMapStateToProps() { const mapDispatchToProps = { fetchImportExclusions, - deleteImportExclusion + deleteImportExclusion, + purgeImportExclusions }; class ImportExclusionsConnector extends Component { - // // Lifecycle @@ -37,6 +41,10 @@ class ImportExclusionsConnector extends Component { this.props.deleteImportExclusion({ id }); }; + onConfirmPurgeImportExclusions = () => { + this.props.purgeImportExclusions(); + }; + // // Render @@ -46,6 +54,7 @@ class ImportExclusionsConnector extends Component { {...this.state} {...this.props} onConfirmDeleteImportExclusion={this.onConfirmDeleteImportExclusion} + onConfirmPurgeImportExclusions={this.onConfirmPurgeImportExclusions} /> ); } @@ -53,7 +62,8 @@ class ImportExclusionsConnector extends Component { ImportExclusionsConnector.propTypes = { fetchImportExclusions: PropTypes.func.isRequired, - deleteImportExclusion: PropTypes.func.isRequired + deleteImportExclusion: PropTypes.func.isRequired, + purgeImportExclusions: PropTypes.func.isRequired }; export default connect(createMapStateToProps, mapDispatchToProps)(ImportExclusionsConnector); diff --git a/frontend/src/Store/Actions/Creators/createPurgeHandler.js b/frontend/src/Store/Actions/Creators/createPurgeHandler.js new file mode 100644 index 000000000..c9a833dd0 --- /dev/null +++ b/frontend/src/Store/Actions/Creators/createPurgeHandler.js @@ -0,0 +1,36 @@ +import createAjaxRequest from 'Utilities/createAjaxRequest'; +import { set } from '../baseActions'; + +function createPurgeHandler(section, url) { + return function(getState, payload, dispatch) { + dispatch(set({ section, isPurging: true })); + + const ajaxOptions = { + url: `${url}/purge`, + method: 'POST' + }; + + const { request } = createAjaxRequest(ajaxOptions); + + request.done((data) => { + dispatch( + set({ + section, + isPurging: false, + purgeError: null + }) + ); + }); + + request.fail((xhr) => { + dispatch( + set({ + section, + isPurging: false + }) + ); + }); + }; +} + +export default createPurgeHandler; diff --git a/frontend/src/Store/Actions/Settings/importExclusions.js b/frontend/src/Store/Actions/Settings/importExclusions.js index 17812fa8f..e2cbc9f47 100644 --- a/frontend/src/Store/Actions/Settings/importExclusions.js +++ b/frontend/src/Store/Actions/Settings/importExclusions.js @@ -4,6 +4,7 @@ import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHand import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; import { createThunk } from 'Store/thunks'; +import createPurgeHandler from '../Creators/createPurgeHandler'; // // Variables @@ -17,6 +18,7 @@ export const FETCH_IMPORT_EXCLUSIONS = 'settings/importExclusions/fetchImportExc export const SAVE_IMPORT_EXCLUSION = 'settings/importExclusions/saveImportExclusion'; export const DELETE_IMPORT_EXCLUSION = 'settings/importExclusions/deleteImportExclusion'; export const SET_IMPORT_EXCLUSION_VALUE = 'settings/importExclusions/setImportExclusionValue'; +export const PURGE_IMPORT_EXCLUSIONS = 'settings/importExclusions/purge'; // // Action Creators @@ -26,6 +28,8 @@ export const fetchImportExclusions = createThunk(FETCH_IMPORT_EXCLUSIONS); export const saveImportExclusion = createThunk(SAVE_IMPORT_EXCLUSION); export const deleteImportExclusion = createThunk(DELETE_IMPORT_EXCLUSION); +export const purgeImportExclusions = createThunk(PURGE_IMPORT_EXCLUSIONS); + export const setImportExclusionValue = createAction(SET_IMPORT_EXCLUSION_VALUE, (payload) => { return { section, @@ -58,7 +62,8 @@ export default { [FETCH_IMPORT_EXCLUSIONS]: createFetchHandler(section, '/exclusions'), [SAVE_IMPORT_EXCLUSION]: createSaveProviderHandler(section, '/exclusions'), - [DELETE_IMPORT_EXCLUSION]: createRemoveItemHandler(section, '/exclusions') + [DELETE_IMPORT_EXCLUSION]: createRemoveItemHandler(section, '/exclusions'), + [PURGE_IMPORT_EXCLUSIONS]: createPurgeHandler(section, '/exclusions') }, // diff --git a/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportExclusionsService.cs b/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportExclusionsService.cs index c94689691..8c4377bad 100644 --- a/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportExclusionsService.cs +++ b/src/NzbDrone.Core/ImportLists/ImportExclusions/ImportExclusionsService.cs @@ -15,6 +15,7 @@ public interface IImportExclusionsService void RemoveExclusion(ImportExclusion exclusion); ImportExclusion GetById(int id); ImportExclusion Update(ImportExclusion exclusion); + void Purge(); } public class ImportExclusionsService : IImportExclusionsService, IHandleAsync @@ -91,5 +92,10 @@ private List DeDupeExclusions(List exclusions) .Where(x => !existingExclusions.Contains(x.TmdbId)) .ToList(); } + + public void Purge() + { + _exclusionRepository.Purge(); + } } } diff --git a/src/Radarr.Api.V3/ImportLists/ImportExclusionsController.cs b/src/Radarr.Api.V3/ImportLists/ImportExclusionsController.cs index e36cb6cdb..a17572674 100644 --- a/src/Radarr.Api.V3/ImportLists/ImportExclusionsController.cs +++ b/src/Radarr.Api.V3/ImportLists/ImportExclusionsController.cs @@ -63,5 +63,11 @@ public void RemoveExclusion(int id) { _exclusionService.RemoveExclusion(new ImportExclusion { Id = id }); } + + [HttpPost("purge")] + public void PurgeExclusions() + { + _exclusionService.Purge(); + } } }