mirror of https://github.com/lidarr/Lidarr
New: Bulk remove from Blacklist
This commit is contained in:
parent
4a9d870720
commit
d7183f999c
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
|
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||||
|
@ -10,11 +11,83 @@ import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||||
import TablePager from 'Components/Table/TablePager';
|
import TablePager from 'Components/Table/TablePager';
|
||||||
import { align, icons } from 'Helpers/Props';
|
import { align, icons, kinds } from 'Helpers/Props';
|
||||||
|
import getRemovedItems from 'Utilities/Object/getRemovedItems';
|
||||||
|
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||||
|
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||||
|
import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
|
||||||
|
import selectAll from 'Utilities/Table/selectAll';
|
||||||
|
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||||
import BlacklistRowConnector from './BlacklistRowConnector';
|
import BlacklistRowConnector from './BlacklistRowConnector';
|
||||||
|
|
||||||
class Blacklist extends Component {
|
class Blacklist extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lifecycle
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
allSelected: false,
|
||||||
|
allUnselected: false,
|
||||||
|
lastToggled: null,
|
||||||
|
selectedState: {},
|
||||||
|
isConfirmRemoveModalOpen: false,
|
||||||
|
items: props.items
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const {
|
||||||
|
items
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (hasDifferentItems(prevProps.items, items)) {
|
||||||
|
this.setState((state) => {
|
||||||
|
return {
|
||||||
|
...removeOldSelectedState(state, getRemovedItems(prevProps.items, items)),
|
||||||
|
items
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Control
|
||||||
|
|
||||||
|
getSelectedIds = () => {
|
||||||
|
return getSelectedIds(this.state.selectedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onSelectAllChange = ({ value }) => {
|
||||||
|
this.setState(selectAll(this.state.selectedState, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectedChange = ({ id, value, shiftKey = false }) => {
|
||||||
|
this.setState((state) => {
|
||||||
|
return toggleSelected(state, this.props.items, id, value, shiftKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveSelectedPress = () => {
|
||||||
|
this.setState({ isConfirmRemoveModalOpen: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveSelectedConfirmed = () => {
|
||||||
|
this.props.onRemoveSelected(this.getSelectedIds());
|
||||||
|
this.setState({ isConfirmRemoveModalOpen: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
onConfirmRemoveModalClose = () => {
|
||||||
|
this.setState({ isConfirmRemoveModalOpen: false });
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
|
@ -28,6 +101,7 @@ class Blacklist extends Component {
|
||||||
items,
|
items,
|
||||||
columns,
|
columns,
|
||||||
totalRecords,
|
totalRecords,
|
||||||
|
isRemoving,
|
||||||
isClearingBlacklistExecuting,
|
isClearingBlacklistExecuting,
|
||||||
onClearBlacklistPress,
|
onClearBlacklistPress,
|
||||||
...otherProps
|
...otherProps
|
||||||
|
@ -36,10 +110,27 @@ class Blacklist extends Component {
|
||||||
const isAllPopulated = isPopulated && isArtistPopulated;
|
const isAllPopulated = isPopulated && isArtistPopulated;
|
||||||
const isAnyFetching = isFetching || isArtistFetching;
|
const isAnyFetching = isFetching || isArtistFetching;
|
||||||
|
|
||||||
|
const {
|
||||||
|
allSelected,
|
||||||
|
allUnselected,
|
||||||
|
selectedState,
|
||||||
|
isConfirmRemoveModalOpen
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
const selectedIds = this.getSelectedIds();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="Blacklist">
|
<PageContent title="Blacklist">
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
<PageToolbarSection>
|
<PageToolbarSection>
|
||||||
|
<PageToolbarButton
|
||||||
|
label="Remove Selected"
|
||||||
|
iconName={icons.REMOVE}
|
||||||
|
isDisabled={!selectedIds.length}
|
||||||
|
isSpinning={isRemoving}
|
||||||
|
onPress={this.onRemoveSelectedPress}
|
||||||
|
/>
|
||||||
|
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Clear"
|
label="Clear"
|
||||||
iconName={icons.CLEAR}
|
iconName={icons.CLEAR}
|
||||||
|
@ -83,8 +174,12 @@ class Blacklist extends Component {
|
||||||
isAllPopulated && !error && !!items.length &&
|
isAllPopulated && !error && !!items.length &&
|
||||||
<div>
|
<div>
|
||||||
<Table
|
<Table
|
||||||
|
selectAll={true}
|
||||||
|
allSelected={allSelected}
|
||||||
|
allUnselected={allUnselected}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
|
onSelectAllChange={this.onSelectAllChange}
|
||||||
>
|
>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{
|
{
|
||||||
|
@ -92,8 +187,10 @@ class Blacklist extends Component {
|
||||||
return (
|
return (
|
||||||
<BlacklistRowConnector
|
<BlacklistRowConnector
|
||||||
key={item.id}
|
key={item.id}
|
||||||
|
isSelected={selectedState[item.id] || false}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
{...item}
|
{...item}
|
||||||
|
onSelectedChange={this.onSelectedChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -109,6 +206,16 @@ class Blacklist extends Component {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
|
|
||||||
|
<ConfirmModal
|
||||||
|
isOpen={isConfirmRemoveModalOpen}
|
||||||
|
kind={kinds.DANGER}
|
||||||
|
title="Remove Selected"
|
||||||
|
message={'Are you sure you want to remove the selected items from the blacklist?'}
|
||||||
|
confirmLabel="Remove Selected"
|
||||||
|
onConfirm={this.onRemoveSelectedConfirmed}
|
||||||
|
onCancel={this.onConfirmRemoveModalClose}
|
||||||
|
/>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +230,9 @@ Blacklist.propTypes = {
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
totalRecords: PropTypes.number,
|
totalRecords: PropTypes.number,
|
||||||
|
isRemoving: PropTypes.bool.isRequired,
|
||||||
isClearingBlacklistExecuting: PropTypes.bool.isRequired,
|
isClearingBlacklistExecuting: PropTypes.bool.isRequired,
|
||||||
|
onRemoveSelected: PropTypes.func.isRequired,
|
||||||
onClearBlacklistPress: PropTypes.func.isRequired
|
onClearBlacklistPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,10 @@ class BlacklistConnector extends Component {
|
||||||
this.props.gotoBlacklistPage({ page });
|
this.props.gotoBlacklistPage({ page });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onRemoveSelected = (ids) => {
|
||||||
|
this.props.removeBlacklistItems({ ids });
|
||||||
|
}
|
||||||
|
|
||||||
onSortPress = (sortKey) => {
|
onSortPress = (sortKey) => {
|
||||||
this.props.setBlacklistSort({ sortKey });
|
this.props.setBlacklistSort({ sortKey });
|
||||||
}
|
}
|
||||||
|
@ -119,6 +123,7 @@ class BlacklistConnector extends Component {
|
||||||
onNextPagePress={this.onNextPagePress}
|
onNextPagePress={this.onNextPagePress}
|
||||||
onLastPagePress={this.onLastPagePress}
|
onLastPagePress={this.onLastPagePress}
|
||||||
onPageSelect={this.onPageSelect}
|
onPageSelect={this.onPageSelect}
|
||||||
|
onRemoveSelected={this.onRemoveSelected}
|
||||||
onSortPress={this.onSortPress}
|
onSortPress={this.onSortPress}
|
||||||
onTableOptionChange={this.onTableOptionChange}
|
onTableOptionChange={this.onTableOptionChange}
|
||||||
onClearBlacklistPress={this.onClearBlacklistPress}
|
onClearBlacklistPress={this.onClearBlacklistPress}
|
||||||
|
@ -138,6 +143,7 @@ BlacklistConnector.propTypes = {
|
||||||
gotoBlacklistNextPage: PropTypes.func.isRequired,
|
gotoBlacklistNextPage: PropTypes.func.isRequired,
|
||||||
gotoBlacklistLastPage: PropTypes.func.isRequired,
|
gotoBlacklistLastPage: PropTypes.func.isRequired,
|
||||||
gotoBlacklistPage: PropTypes.func.isRequired,
|
gotoBlacklistPage: PropTypes.func.isRequired,
|
||||||
|
removeBlacklistItems: PropTypes.func.isRequired,
|
||||||
setBlacklistSort: PropTypes.func.isRequired,
|
setBlacklistSort: PropTypes.func.isRequired,
|
||||||
setBlacklistTableOption: PropTypes.func.isRequired,
|
setBlacklistTableOption: PropTypes.func.isRequired,
|
||||||
clearBlacklist: PropTypes.func.isRequired,
|
clearBlacklist: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ArtistNameLink from 'Artist/ArtistNameLink';
|
||||||
import IconButton from 'Components/Link/IconButton';
|
import IconButton from 'Components/Link/IconButton';
|
||||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
|
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
import BlacklistDetailsModal from './BlacklistDetailsModal';
|
import BlacklistDetailsModal from './BlacklistDetailsModal';
|
||||||
|
@ -39,6 +40,7 @@ class BlacklistRow extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
id,
|
||||||
artist,
|
artist,
|
||||||
sourceTitle,
|
sourceTitle,
|
||||||
quality,
|
quality,
|
||||||
|
@ -46,7 +48,9 @@ class BlacklistRow extends Component {
|
||||||
protocol,
|
protocol,
|
||||||
indexer,
|
indexer,
|
||||||
message,
|
message,
|
||||||
|
isSelected,
|
||||||
columns,
|
columns,
|
||||||
|
onSelectedChange,
|
||||||
onRemovePress
|
onRemovePress
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -56,6 +60,12 @@ class BlacklistRow extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
<TableSelectCell
|
||||||
|
id={id}
|
||||||
|
isSelected={isSelected}
|
||||||
|
onSelectedChange={onSelectedChange}
|
||||||
|
/>
|
||||||
|
|
||||||
{
|
{
|
||||||
columns.map((column) => {
|
columns.map((column) => {
|
||||||
const {
|
const {
|
||||||
|
@ -167,7 +177,9 @@ BlacklistRow.propTypes = {
|
||||||
protocol: PropTypes.string.isRequired,
|
protocol: PropTypes.string.isRequired,
|
||||||
indexer: PropTypes.string,
|
indexer: PropTypes.string,
|
||||||
message: PropTypes.string,
|
message: PropTypes.string,
|
||||||
|
isSelected: PropTypes.bool.isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
onSelectedChange: PropTypes.func.isRequired,
|
||||||
onRemovePress: PropTypes.func.isRequired
|
onRemovePress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { removeFromBlacklist } from 'Store/Actions/blacklistActions';
|
import { removeBlacklistItem } from 'Store/Actions/blacklistActions';
|
||||||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||||
import BlacklistRow from './BlacklistRow';
|
import BlacklistRow from './BlacklistRow';
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ function createMapStateToProps() {
|
||||||
function createMapDispatchToProps(dispatch, props) {
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
return {
|
return {
|
||||||
onRemovePress() {
|
onRemovePress() {
|
||||||
dispatch(removeFromBlacklist({ id: props.id }));
|
dispatch(removeBlacklistItem({ id: props.id }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
|
import { batchActions } from 'redux-batched-actions';
|
||||||
import { sortDirections } from 'Helpers/Props';
|
import { sortDirections } from 'Helpers/Props';
|
||||||
import { createThunk, handleThunks } from 'Store/thunks';
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||||
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
|
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
|
||||||
|
import { set, updateItem } from './baseActions';
|
||||||
import createHandleActions from './Creators/createHandleActions';
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
||||||
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
|
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
|
||||||
|
@ -24,6 +27,7 @@ export const defaultState = {
|
||||||
sortDirection: sortDirections.DESCENDING,
|
sortDirection: sortDirections.DESCENDING,
|
||||||
error: null,
|
error: null,
|
||||||
items: [],
|
items: [],
|
||||||
|
isRemoving: false,
|
||||||
|
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
|
@ -82,7 +86,8 @@ export const GOTO_LAST_BLACKLIST_PAGE = 'blacklist/gotoBlacklistLastPage';
|
||||||
export const GOTO_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPage';
|
export const GOTO_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPage';
|
||||||
export const SET_BLACKLIST_SORT = 'blacklist/setBlacklistSort';
|
export const SET_BLACKLIST_SORT = 'blacklist/setBlacklistSort';
|
||||||
export const SET_BLACKLIST_TABLE_OPTION = 'blacklist/setBlacklistTableOption';
|
export const SET_BLACKLIST_TABLE_OPTION = 'blacklist/setBlacklistTableOption';
|
||||||
export const REMOVE_FROM_BLACKLIST = 'blacklist/removeFromBlacklist';
|
export const REMOVE_BLACKLIST_ITEM = 'blacklist/removeBlacklistItem';
|
||||||
|
export const REMOVE_BLACKLIST_ITEMS = 'blacklist/removeBlacklistItems';
|
||||||
export const CLEAR_BLACKLIST = 'blacklist/clearBlacklist';
|
export const CLEAR_BLACKLIST = 'blacklist/clearBlacklist';
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -96,7 +101,8 @@ export const gotoBlacklistLastPage = createThunk(GOTO_LAST_BLACKLIST_PAGE);
|
||||||
export const gotoBlacklistPage = createThunk(GOTO_BLACKLIST_PAGE);
|
export const gotoBlacklistPage = createThunk(GOTO_BLACKLIST_PAGE);
|
||||||
export const setBlacklistSort = createThunk(SET_BLACKLIST_SORT);
|
export const setBlacklistSort = createThunk(SET_BLACKLIST_SORT);
|
||||||
export const setBlacklistTableOption = createAction(SET_BLACKLIST_TABLE_OPTION);
|
export const setBlacklistTableOption = createAction(SET_BLACKLIST_TABLE_OPTION);
|
||||||
export const removeFromBlacklist = createThunk(REMOVE_FROM_BLACKLIST);
|
export const removeBlacklistItem = createThunk(REMOVE_BLACKLIST_ITEM);
|
||||||
|
export const removeBlacklistItems = createThunk(REMOVE_BLACKLIST_ITEMS);
|
||||||
export const clearBlacklist = createAction(CLEAR_BLACKLIST);
|
export const clearBlacklist = createAction(CLEAR_BLACKLIST);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -117,7 +123,53 @@ export const actionHandlers = handleThunks({
|
||||||
[serverSideCollectionHandlers.SORT]: SET_BLACKLIST_SORT
|
[serverSideCollectionHandlers.SORT]: SET_BLACKLIST_SORT
|
||||||
}),
|
}),
|
||||||
|
|
||||||
[REMOVE_FROM_BLACKLIST]: createRemoveItemHandler(section, '/blacklist')
|
[REMOVE_BLACKLIST_ITEM]: createRemoveItemHandler(section, '/blacklist'),
|
||||||
|
|
||||||
|
[REMOVE_BLACKLIST_ITEMS]: function(getState, payload, dispatch) {
|
||||||
|
const {
|
||||||
|
ids
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
dispatch(batchActions([
|
||||||
|
...ids.map((id) => {
|
||||||
|
return updateItem({
|
||||||
|
section,
|
||||||
|
id,
|
||||||
|
isRemoving: true
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
set({ section, isRemoving: true })
|
||||||
|
]));
|
||||||
|
|
||||||
|
const promise = createAjaxRequest({
|
||||||
|
url: '/blacklist/bulk',
|
||||||
|
method: 'DELETE',
|
||||||
|
dataType: 'json',
|
||||||
|
data: JSON.stringify({ ids })
|
||||||
|
}).request;
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
// Don't use batchActions with thunks
|
||||||
|
dispatch(fetchBlacklist());
|
||||||
|
|
||||||
|
dispatch(set({ section, isRemoving: false }));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
...ids.map((id) => {
|
||||||
|
return updateItem({
|
||||||
|
section,
|
||||||
|
id,
|
||||||
|
isRemoving: false
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
set({ section, isRemoving: false })
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -306,9 +306,9 @@ export const actionHandlers = handleThunks({
|
||||||
}).request;
|
}).request;
|
||||||
|
|
||||||
promise.done((data) => {
|
promise.done((data) => {
|
||||||
dispatch(batchActions([
|
dispatch(fetchQueue());
|
||||||
fetchQueue(),
|
|
||||||
|
|
||||||
|
dispatch(batchActions([
|
||||||
...ids.map((id) => {
|
...ids.map((id) => {
|
||||||
return updateItem({
|
return updateItem({
|
||||||
section: paged,
|
section: paged,
|
||||||
|
@ -394,10 +394,10 @@ export const actionHandlers = handleThunks({
|
||||||
}).request;
|
}).request;
|
||||||
|
|
||||||
promise.done((data) => {
|
promise.done((data) => {
|
||||||
dispatch(batchActions([
|
// Don't use batchActions with thunks
|
||||||
set({ section: paged, isRemoving: false }),
|
dispatch(fetchQueue());
|
||||||
fetchQueue()
|
|
||||||
]));
|
dispatch(set({ section: paged, isRemoving: false }));
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
promise.fail((xhr) => {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Lidarr.Api.V1.Blacklist
|
||||||
|
{
|
||||||
|
public class BlacklistBulkResource
|
||||||
|
{
|
||||||
|
public List<int> Ids { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using Lidarr.Http;
|
using Lidarr.Http;
|
||||||
|
using Lidarr.Http.Extensions;
|
||||||
using NzbDrone.Core.Blacklisting;
|
using NzbDrone.Core.Blacklisting;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
@ -13,6 +14,8 @@ namespace Lidarr.Api.V1.Blacklist
|
||||||
_blacklistService = blacklistService;
|
_blacklistService = blacklistService;
|
||||||
GetResourcePaged = GetBlacklist;
|
GetResourcePaged = GetBlacklist;
|
||||||
DeleteResource = DeleteBlacklist;
|
DeleteResource = DeleteBlacklist;
|
||||||
|
|
||||||
|
Delete("/bulk", x => Remove());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PagingResource<BlacklistResource> GetBlacklist(PagingResource<BlacklistResource> pagingResource)
|
private PagingResource<BlacklistResource> GetBlacklist(PagingResource<BlacklistResource> pagingResource)
|
||||||
|
@ -26,5 +29,14 @@ namespace Lidarr.Api.V1.Blacklist
|
||||||
{
|
{
|
||||||
_blacklistService.Delete(id);
|
_blacklistService.Delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object Remove()
|
||||||
|
{
|
||||||
|
var resource = Request.Body.FromJson<BlacklistBulkResource>();
|
||||||
|
|
||||||
|
_blacklistService.Delete(resource.Ids);
|
||||||
|
|
||||||
|
return new object();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
bool Blacklisted(int artistId, ReleaseInfo release);
|
bool Blacklisted(int artistId, ReleaseInfo release);
|
||||||
PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec);
|
PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec);
|
||||||
void Delete(int id);
|
void Delete(int id);
|
||||||
|
void Delete(List<int> ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlacklistService : IBlacklistService,
|
public class BlacklistService : IBlacklistService,
|
||||||
|
@ -70,6 +71,11 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
_blacklistRepository.Delete(id);
|
_blacklistRepository.Delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Delete(List<int> ids)
|
||||||
|
{
|
||||||
|
_blacklistRepository.DeleteMany(ids);
|
||||||
|
}
|
||||||
|
|
||||||
private bool SameNzb(Blacklist item, ReleaseInfo release)
|
private bool SameNzb(Blacklist item, ReleaseInfo release)
|
||||||
{
|
{
|
||||||
if (item.PublishedDate == release.PublishDate)
|
if (item.PublishedDate == release.PublishDate)
|
||||||
|
|
Loading…
Reference in New Issue