-
@@ -136,14 +136,14 @@ class MovieEditorFooter extends Component {
-
@@ -151,8 +151,8 @@ class MovieEditorFooter extends Component {
}
}
-MovieEditorFooter.propTypes = {
- movieIds: PropTypes.arrayOf(PropTypes.number).isRequired,
+IndexerEditorFooter.propTypes = {
+ indexerIds: PropTypes.arrayOf(PropTypes.number).isRequired,
selectedCount: PropTypes.number.isRequired,
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
@@ -161,4 +161,4 @@ MovieEditorFooter.propTypes = {
onSaveSelected: PropTypes.func.isRequired
};
-export default MovieEditorFooter;
+export default IndexerEditorFooter;
diff --git a/frontend/src/Indexer/Editor/MovieEditorFooterLabel.css b/frontend/src/Indexer/Editor/IndexerEditorFooterLabel.css
similarity index 100%
rename from frontend/src/Indexer/Editor/MovieEditorFooterLabel.css
rename to frontend/src/Indexer/Editor/IndexerEditorFooterLabel.css
diff --git a/frontend/src/Indexer/Editor/MovieEditorFooterLabel.js b/frontend/src/Indexer/Editor/IndexerEditorFooterLabel.js
similarity index 74%
rename from frontend/src/Indexer/Editor/MovieEditorFooterLabel.js
rename to frontend/src/Indexer/Editor/IndexerEditorFooterLabel.js
index 805ecd39e..e498d1480 100644
--- a/frontend/src/Indexer/Editor/MovieEditorFooterLabel.js
+++ b/frontend/src/Indexer/Editor/IndexerEditorFooterLabel.js
@@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
import React from 'react';
import SpinnerIcon from 'Components/SpinnerIcon';
import { icons } from 'Helpers/Props';
-import styles from './MovieEditorFooterLabel.css';
+import styles from './IndexerEditorFooterLabel.css';
-function MovieEditorFooterLabel(props) {
+function IndexerEditorFooterLabel(props) {
const {
className,
label,
@@ -27,14 +27,14 @@ function MovieEditorFooterLabel(props) {
);
}
-MovieEditorFooterLabel.propTypes = {
+IndexerEditorFooterLabel.propTypes = {
className: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
isSaving: PropTypes.bool.isRequired
};
-MovieEditorFooterLabel.defaultProps = {
+IndexerEditorFooterLabel.defaultProps = {
className: styles.label
};
-export default MovieEditorFooterLabel;
+export default IndexerEditorFooterLabel;
diff --git a/frontend/src/Indexer/Editor/Tags/TagsModalContentConnector.js b/frontend/src/Indexer/Editor/Tags/TagsModalContentConnector.js
index 75d2006d4..8b7d74f50 100644
--- a/frontend/src/Indexer/Editor/Tags/TagsModalContentConnector.js
+++ b/frontend/src/Indexer/Editor/Tags/TagsModalContentConnector.js
@@ -1,17 +1,17 @@
import _ from 'lodash';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
-import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector';
+import createAllIndexersSelector from 'Store/Selectors/createAllIndexersSelector';
import createTagsSelector from 'Store/Selectors/createTagsSelector';
import TagsModalContent from './TagsModalContent';
function createMapStateToProps() {
return createSelector(
- (state, { movieIds }) => movieIds,
- createAllMoviesSelector(),
+ (state, { indexerIds }) => indexerIds,
+ createAllIndexersSelector(),
createTagsSelector(),
- (movieIds, allMovies, tagList) => {
- const movies = _.intersectionWith(allMovies, movieIds, (s, id) => {
+ (indexerIds, allMovies, tagList) => {
+ const movies = _.intersectionWith(allMovies, indexerIds, (s, id) => {
return s.id === id;
});
diff --git a/frontend/src/Indexer/Index/IndexerIndex.js b/frontend/src/Indexer/Index/IndexerIndex.js
index 956c3b2c7..a10e1f74d 100644
--- a/frontend/src/Indexer/Index/IndexerIndex.js
+++ b/frontend/src/Indexer/Index/IndexerIndex.js
@@ -11,7 +11,7 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import { align, icons, sortDirections } from 'Helpers/Props';
-import MovieEditorFooter from 'Indexer/Editor/MovieEditorFooter.js';
+import IndexerEditorFooter from 'Indexer/Editor/IndexerEditorFooter.js';
import NoIndexer from 'Indexer/NoIndexer';
import AddIndexerModal from 'Settings/Indexers/Indexers/AddIndexerModal';
import EditIndexerModalConnector from 'Settings/Indexers/Indexers/EditIndexerModalConnector';
@@ -444,8 +444,8 @@ class IndexerIndex extends Component {
{
isLoaded && isMovieEditorActive &&
- movieIds,
- createAllMoviesSelector(),
+ (state, { indexerIds }) => indexerIds,
+ createAllIndexersSelector(),
findMatchingItems
);
}
@@ -37,14 +37,6 @@ function createMatchingMoviesSelector() {
);
}
-function createMatchingDelayProfilesSelector() {
- return createSelector(
- (state, { delayProfileIds }) => delayProfileIds,
- (state) => state.settings.delayProfiles.items,
- findMatchingItems
- );
-}
-
function createMatchingNotificationsSelector() {
return createSelector(
(state, { notificationIds }) => notificationIds,
@@ -53,26 +45,14 @@ function createMatchingNotificationsSelector() {
);
}
-function createMatchingRestrictionsSelector() {
- return createSelector(
- (state, { restrictionIds }) => restrictionIds,
- (state) => state.settings.restrictions.items,
- findMatchingItems
- );
-}
-
function createMapStateToProps() {
return createSelector(
createMatchingMoviesSelector(),
- createMatchingDelayProfilesSelector(),
createMatchingNotificationsSelector(),
- createMatchingRestrictionsSelector(),
- (movies, delayProfiles, notifications, restrictions) => {
+ (movies, notifications) => {
return {
movies,
- delayProfiles,
- notifications,
- restrictions
+ notifications
};
}
);
diff --git a/frontend/src/Store/Actions/indexerIndexActions.js b/frontend/src/Store/Actions/indexerIndexActions.js
index 5317d70d5..8bd6a62b0 100644
--- a/frontend/src/Store/Actions/indexerIndexActions.js
+++ b/frontend/src/Store/Actions/indexerIndexActions.js
@@ -4,7 +4,7 @@ import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Hel
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import translate from 'Utilities/String/translate';
-import { set, updateItem } from './baseActions';
+import { removeItem, set, updateItem } from './baseActions';
import createHandleActions from './Creators/createHandleActions';
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
@@ -24,9 +24,9 @@ export const defaultState = {
saveError: null,
isDeleting: false,
deleteError: null,
- sortKey: 'sortTitle',
+ sortKey: 'name',
sortDirection: sortDirections.ASCENDING,
- secondarySortKey: 'sortTitle',
+ secondarySortKey: 'name',
secondarySortDirection: sortDirections.ASCENDING,
tableOptions: {
@@ -105,7 +105,7 @@ export const defaultState = {
filterBuilderProps: [
{
- name: 'title',
+ name: 'name',
label: 'Indexer Name',
type: filterBuilderTypes.STRING
},
@@ -142,7 +142,7 @@ export const SET_MOVIE_FILTER = 'indexerIndex/setMovieFilter';
export const SET_MOVIE_VIEW = 'indexerIndex/setMovieView';
export const SET_MOVIE_TABLE_OPTION = 'indexerIndex/setMovieTableOption';
export const SAVE_MOVIE_EDITOR = 'indexerIndex/saveMovieEditor';
-export const BULK_DELETE_MOVIE = 'indexerIndex/bulkDeleteMovie';
+export const BULK_DELETE_INDEXERS = 'indexerIndex/bulkDeleteIndexers';
//
// Action Creators
@@ -152,7 +152,7 @@ export const setMovieFilter = createAction(SET_MOVIE_FILTER);
export const setMovieView = createAction(SET_MOVIE_VIEW);
export const setMovieTableOption = createAction(SET_MOVIE_TABLE_OPTION);
export const saveMovieEditor = createThunk(SAVE_MOVIE_EDITOR);
-export const bulkDeleteMovie = createThunk(BULK_DELETE_MOVIE);
+export const bulkDeleteIndexers = createThunk(BULK_DELETE_INDEXERS);
//
// Action Handlers
@@ -198,27 +198,31 @@ export const actionHandlers = handleThunks({
});
},
- [BULK_DELETE_MOVIE]: function(getState, payload, dispatch) {
+ [BULK_DELETE_INDEXERS]: function(getState, payload, dispatch) {
dispatch(set({
section,
isDeleting: true
}));
const promise = createAjaxRequest({
- url: '/movie/editor',
+ url: '/indexer/editor',
method: 'DELETE',
data: JSON.stringify(payload),
dataType: 'json'
}).request;
promise.done(() => {
- // SignaR will take care of removing the movie from the collection
+ dispatch(batchActions([
+ ...payload.indexerIds.map((id) => {
+ return removeItem({ section: 'indexers', id });
+ }),
- dispatch(set({
- section,
- isDeleting: false,
- deleteError: null
- }));
+ set({
+ section,
+ isDeleting: false,
+ deleteError: null
+ })
+ ]));
});
promise.fail((xhr) => {
diff --git a/frontend/src/Store/Selectors/createAllIndexersSelector.js b/frontend/src/Store/Selectors/createAllIndexersSelector.js
new file mode 100644
index 000000000..178c54eed
--- /dev/null
+++ b/frontend/src/Store/Selectors/createAllIndexersSelector.js
@@ -0,0 +1,12 @@
+import { createSelector } from 'reselect';
+
+function createAllIndexersSelector() {
+ return createSelector(
+ (state) => state.indexers,
+ (indexers) => {
+ return indexers.items;
+ }
+ );
+}
+
+export default createAllIndexersSelector;
diff --git a/frontend/src/Store/Selectors/createAllMoviesSelector.js b/frontend/src/Store/Selectors/createAllMoviesSelector.js
deleted file mode 100644
index a6bad0991..000000000
--- a/frontend/src/Store/Selectors/createAllMoviesSelector.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { createSelector } from 'reselect';
-
-function createAllMoviesSelector() {
- return createSelector(
- (state) => state.movies,
- (movies) => {
- return movies.items;
- }
- );
-}
-
-export default createAllMoviesSelector;
diff --git a/src/NzbDrone.Core/Indexers/IndexerFactory.cs b/src/NzbDrone.Core/Indexers/IndexerFactory.cs
index b8f4187f4..8db47837b 100644
--- a/src/NzbDrone.Core/Indexers/IndexerFactory.cs
+++ b/src/NzbDrone.Core/Indexers/IndexerFactory.cs
@@ -14,6 +14,7 @@ namespace NzbDrone.Core.Indexers
List RssEnabled(bool filterBlockedIndexers = true);
List AutomaticSearchEnabled(bool filterBlockedIndexers = true);
List InteractiveSearchEnabled(bool filterBlockedIndexers = true);
+ void DeleteIndexers(List indexerIds);
}
public class IndexerFactory : ProviderFactory, IIndexerFactory
@@ -102,6 +103,18 @@ namespace NzbDrone.Core.Indexers
}
}
+ public void DeleteIndexers(List indexerIds)
+ {
+ var indexersToDelete = _providerRepository.Get(indexerIds).ToList();
+
+ _providerRepository.DeleteMany(indexerIds);
+
+ foreach (var indexer in indexersToDelete)
+ {
+ _logger.Info("Deleted indexer {0}", indexer.Name);
+ }
+ }
+
public override ValidationResult Test(IndexerDefinition definition)
{
var result = base.Test(definition);
diff --git a/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs b/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs
index b37aefda9..60dbc8e99 100644
--- a/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs
+++ b/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.ThingiProvider
where TProviderDefinition : ProviderDefinition, new()
where TProvider : IProvider
{
- private readonly IProviderRepository _providerRepository;
+ protected readonly IProviderRepository _providerRepository;
private readonly IContainer _container;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
diff --git a/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs b/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs
index 695bdff4d..332533bb2 100644
--- a/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs
+++ b/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs
@@ -8,7 +8,7 @@ using Prowlarr.Http.Extensions;
namespace Prowlarr.Api.V1.FileSystem
{
- public class FileSystemModule : ProwlarrV3Module
+ public class FileSystemModule : ProwlarrV1Module
{
private readonly IFileSystemLookupService _fileSystemLookupService;
private readonly IDiskProvider _diskProvider;
diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerEditorModule.cs b/src/Prowlarr.Api.V1/Indexers/IndexerEditorModule.cs
new file mode 100644
index 000000000..4f0864de6
--- /dev/null
+++ b/src/Prowlarr.Api.V1/Indexers/IndexerEditorModule.cs
@@ -0,0 +1,30 @@
+using Nancy;
+using NzbDrone.Core.Indexers;
+using NzbDrone.Core.Messaging.Commands;
+using Prowlarr.Http.Extensions;
+
+namespace Prowlarr.Api.V1.Indexers
+{
+ public class IndexerEditorModule : ProwlarrV1Module
+ {
+ private readonly IIndexerFactory _movieService;
+ private readonly IManageCommandQueue _commandQueueManager;
+
+ public IndexerEditorModule(IIndexerFactory movieService, IManageCommandQueue commandQueueManager)
+ : base("/indexer/editor")
+ {
+ _movieService = movieService;
+ _commandQueueManager = commandQueueManager;
+ Delete("/", movie => DeleteIndexers());
+ }
+
+ private object DeleteIndexers()
+ {
+ var resource = Request.Body.FromJson();
+
+ _movieService.DeleteIndexers(resource.IndexerIds);
+
+ return new object();
+ }
+ }
+}
diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerEditorResource.cs b/src/Prowlarr.Api.V1/Indexers/IndexerEditorResource.cs
new file mode 100644
index 000000000..569cbf067
--- /dev/null
+++ b/src/Prowlarr.Api.V1/Indexers/IndexerEditorResource.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Prowlarr.Api.V1.Indexers
+{
+ public class IndexerEditorResource
+ {
+ public List IndexerIds { get; set; }
+ }
+}
diff --git a/src/Prowlarr.Api.V1/ProwlarrV1Module.cs b/src/Prowlarr.Api.V1/ProwlarrV1Module.cs
index b9eb66001..dd814a461 100644
--- a/src/Prowlarr.Api.V1/ProwlarrV1Module.cs
+++ b/src/Prowlarr.Api.V1/ProwlarrV1Module.cs
@@ -2,9 +2,9 @@ using Prowlarr.Http;
namespace Prowlarr.Api.V1
{
- public abstract class ProwlarrV3Module : ProwlarrModule
+ public abstract class ProwlarrV1Module : ProwlarrModule
{
- protected ProwlarrV3Module(string resource)
+ protected ProwlarrV1Module(string resource)
: base("/api/v1/" + resource.Trim('/'))
{
}
diff --git a/src/Prowlarr.Api.V1/System/SystemModule.cs b/src/Prowlarr.Api.V1/System/SystemModule.cs
index 750b0417f..6753d84a3 100644
--- a/src/Prowlarr.Api.V1/System/SystemModule.cs
+++ b/src/Prowlarr.Api.V1/System/SystemModule.cs
@@ -8,7 +8,7 @@ using NzbDrone.Core.Lifecycle;
namespace Prowlarr.Api.V1.System
{
- public class SystemModule : ProwlarrV3Module
+ public class SystemModule : ProwlarrV1Module
{
private readonly IAppFolderInfo _appFolderInfo;
private readonly IRuntimeInfo _runtimeInfo;