diff --git a/frontend/src/Commands/commandNames.js b/frontend/src/Commands/commandNames.js
index ac6fd2b27..7028d46cd 100644
--- a/frontend/src/Commands/commandNames.js
+++ b/frontend/src/Commands/commandNames.js
@@ -1,5 +1,6 @@
export const APPLICATION_UPDATE = 'ApplicationUpdate';
export const BACKUP = 'Backup';
+export const CLEAR_HISTORY = 'ClearHistory';
export const CLEAR_LOGS = 'ClearLog';
export const DELETE_LOG_FILES = 'DeleteLogFiles';
export const DELETE_UPDATE_LOG_FILES = 'DeleteUpdateLogFiles';
diff --git a/frontend/src/History/History.js b/frontend/src/History/History.js
index 9cb71c1df..c4fb34fe4 100644
--- a/frontend/src/History/History.js
+++ b/frontend/src/History/History.js
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FilterMenu from 'Components/Menu/FilterMenu';
+import ConfirmModal from 'Components/Modal/ConfirmModal';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
@@ -11,13 +12,40 @@ import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import TablePager from 'Components/Table/TablePager';
-import { align, icons } from 'Helpers/Props';
+import { align, icons, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import HistoryOptionsConnector from './HistoryOptionsConnector';
import HistoryRowConnector from './HistoryRowConnector';
class History extends Component {
+ //
+ // Lifecycle
+
+ constructor(props, context) {
+ super(props, context);
+
+ this.state = {
+ isClearHistoryModalOpen: false
+ };
+ }
+
+ //
+ // Listeners
+
+ onClearHistoryPress = () => {
+ this.setState({ isClearHistoryModalOpen: true });
+ }
+
+ onClearHistoryModalClose = () => {
+ this.setState({ isClearHistoryModalOpen: false });
+ }
+
+ onConfirmClearHistory = () => {
+ this.setState({ isClearHistoryModalOpen: false });
+ this.props.onClearHistoryPress();
+ }
+
//
// Render
@@ -25,9 +53,10 @@ class History extends Component {
const {
isFetching,
isPopulated,
+ isHistoryClearing,
error,
- isMoviesFetching,
- isMoviesPopulated,
+ isIndexersFetching,
+ isIndexersPopulated,
indexersError,
items,
columns,
@@ -36,11 +65,12 @@ class History extends Component {
totalRecords,
onFilterSelect,
onFirstPagePress,
+ onClearHistoryPress,
...otherProps
} = this.props;
- const isFetchingAny = isFetching || isMoviesFetching;
- const isAllPopulated = isPopulated && (isMoviesPopulated || !items.length);
+ const isFetchingAny = isFetching || isIndexersFetching;
+ const isAllPopulated = isPopulated && (isIndexersPopulated || !items.length);
const hasError = error || indexersError;
return (
@@ -53,6 +83,12 @@ class History extends Component {
isSpinning={isFetching}
onPress={onFirstPagePress}
/>
+
@@ -131,6 +167,16 @@ class History extends Component {
}
+
+
);
}
@@ -139,9 +185,10 @@ class History extends Component {
History.propTypes = {
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired,
+ isHistoryClearing: PropTypes.bool.isRequired,
error: PropTypes.object,
- isMoviesFetching: PropTypes.bool.isRequired,
- isMoviesPopulated: PropTypes.bool.isRequired,
+ isIndexersFetching: PropTypes.bool.isRequired,
+ isIndexersPopulated: PropTypes.bool.isRequired,
indexersError: PropTypes.object,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
@@ -149,7 +196,8 @@ History.propTypes = {
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
totalRecords: PropTypes.number,
onFilterSelect: PropTypes.func.isRequired,
- onFirstPagePress: PropTypes.func.isRequired
+ onFirstPagePress: PropTypes.func.isRequired,
+ onClearHistoryPress: PropTypes.func.isRequired
};
export default History;
diff --git a/frontend/src/History/HistoryConnector.js b/frontend/src/History/HistoryConnector.js
index bd4308afc..cede42e57 100644
--- a/frontend/src/History/HistoryConnector.js
+++ b/frontend/src/History/HistoryConnector.js
@@ -2,8 +2,11 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
+import * as commandNames from 'Commands/commandNames';
import withCurrentPage from 'Components/withCurrentPage';
+import { executeCommand } from 'Store/Actions/commandActions';
import * as historyActions from 'Store/Actions/historyActions';
+import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
import History from './History';
@@ -11,11 +14,13 @@ function createMapStateToProps() {
return createSelector(
(state) => state.history,
(state) => state.indexers,
- (history, indexers) => {
+ createCommandExecutingSelector(commandNames.CLEAR_HISTORY),
+ (history, indexers, isHistoryClearing) => {
return {
- isMoviesFetching: indexers.isFetching,
- isMoviesPopulated: indexers.isPopulated,
+ isIndexersFetching: indexers.isFetching,
+ isIndexersPopulated: indexers.isPopulated,
indexersError: indexers.error,
+ isHistoryClearing,
...history
};
}
@@ -23,6 +28,7 @@ function createMapStateToProps() {
}
const mapDispatchToProps = {
+ executeCommand,
...historyActions
};
@@ -47,6 +53,12 @@ class HistoryConnector extends Component {
}
}
+ componentDidUpdate(prevProps) {
+ if (prevProps.isHistoryClearing && !this.props.isHistoryClearing) {
+ this.props.gotoHistoryFirstPage();
+ }
+ }
+
componentWillUnmount() {
unregisterPagePopulator(this.repopulate);
this.props.clearHistory();
@@ -90,6 +102,10 @@ class HistoryConnector extends Component {
this.props.setHistoryFilter({ selectedFilterKey });
}
+ onClearHistoryPress = () => {
+ this.props.executeCommand({ name: commandNames.CLEAR_HISTORY });
+ }
+
onTableOptionChange = (payload) => {
this.props.setHistoryTableOption(payload);
@@ -112,6 +128,7 @@ class HistoryConnector extends Component {
onSortPress={this.onSortPress}
onFilterSelect={this.onFilterSelect}
onTableOptionChange={this.onTableOptionChange}
+ onClearHistoryPress={this.onClearHistoryPress}
{...this.props}
/>
);
@@ -122,6 +139,8 @@ HistoryConnector.propTypes = {
useCurrentPage: PropTypes.bool.isRequired,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
fetchHistory: PropTypes.func.isRequired,
+ clearHistory: PropTypes.func.isRequired,
+ isHistoryClearing: PropTypes.bool.isRequired,
gotoHistoryFirstPage: PropTypes.func.isRequired,
gotoHistoryPreviousPage: PropTypes.func.isRequired,
gotoHistoryNextPage: PropTypes.func.isRequired,
@@ -130,7 +149,7 @@ HistoryConnector.propTypes = {
setHistorySort: PropTypes.func.isRequired,
setHistoryFilter: PropTypes.func.isRequired,
setHistoryTableOption: PropTypes.func.isRequired,
- clearHistory: PropTypes.func.isRequired
+ executeCommand: PropTypes.func.isRequired
};
export default withCurrentPage(
diff --git a/frontend/src/History/HistoryRow.js b/frontend/src/History/HistoryRow.js
index 9f66e7194..d45fd3770 100644
--- a/frontend/src/History/HistoryRow.js
+++ b/frontend/src/History/HistoryRow.js
@@ -51,8 +51,6 @@ class HistoryRow extends Component {
});
}
- console.log(categories);
-
this.props.onSearchPress(data.query, indexer.id, categories);
}
diff --git a/frontend/src/Search/SearchFooterConnector.js b/frontend/src/Search/SearchFooterConnector.js
index f5647fe77..c4afc5979 100644
--- a/frontend/src/Search/SearchFooterConnector.js
+++ b/frontend/src/Search/SearchFooterConnector.js
@@ -34,7 +34,6 @@ class SearchFooterConnector extends Component {
// Listeners
onInputChange = ({ name, value }) => {
- console.log(name, value);
this.props.setSearchDefault({ [name]: value });
}
diff --git a/frontend/src/Store/Actions/releaseActions.js b/frontend/src/Store/Actions/releaseActions.js
index d1dc5237d..b9272ef9c 100644
--- a/frontend/src/Store/Actions/releaseActions.js
+++ b/frontend/src/Store/Actions/releaseActions.js
@@ -108,7 +108,6 @@ export const defaultState = {
sortPredicates: {
age: function(item) {
- console.log(item);
return item.ageMinutes;
},
diff --git a/src/NzbDrone.Core/History/CleanupHistoryCommand.cs b/src/NzbDrone.Core/History/Commands/CleanupHistoryCommand.cs
similarity index 100%
rename from src/NzbDrone.Core/History/CleanupHistoryCommand.cs
rename to src/NzbDrone.Core/History/Commands/CleanupHistoryCommand.cs
diff --git a/src/NzbDrone.Core/History/Commands/ClearHistoryCommand.cs b/src/NzbDrone.Core/History/Commands/ClearHistoryCommand.cs
new file mode 100644
index 000000000..c5c8ba14a
--- /dev/null
+++ b/src/NzbDrone.Core/History/Commands/ClearHistoryCommand.cs
@@ -0,0 +1,9 @@
+using NzbDrone.Core.Messaging.Commands;
+
+namespace NzbDrone.Core.History
+{
+ public class ClearHistoryCommand : Command
+ {
+ public override bool SendUpdatesToClient => true;
+ }
+}
diff --git a/src/NzbDrone.Core/History/HistoryService.cs b/src/NzbDrone.Core/History/HistoryService.cs
index 0f9c56f88..86a7dccb0 100644
--- a/src/NzbDrone.Core/History/HistoryService.cs
+++ b/src/NzbDrone.Core/History/HistoryService.cs
@@ -31,7 +31,8 @@ namespace NzbDrone.Core.History
IHandle,
IHandle,
IHandle,
- IExecute
+ IExecute,
+ IExecute
{
private readonly IHistoryRepository _historyRepository;
private readonly IConfigService _configService;
@@ -197,5 +198,10 @@ namespace NzbDrone.Core.History
{
Cleanup();
}
+
+ public void Execute(ClearHistoryCommand message)
+ {
+ _historyRepository.Purge(vacuum: true);
+ }
}
}
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 7cd380757..9d2938823 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -47,6 +47,8 @@
"CertificateValidationHelpText": "Change how strict HTTPS certification validation is",
"ChangeHasNotBeenSavedYet": "Change has not been saved yet",
"Clear": "Clear",
+ "ClearHistory": "Clear History",
+ "ClearHistoryMessageText": "Are you sure you want to clear all Prowlarr history?",
"ClientPriority": "Client Priority",
"CloneIndexer": "Clone Indexer",
"Close": "Close",