mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
New: Clear all history from History page
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
export const APPLICATION_UPDATE = 'ApplicationUpdate';
|
export const APPLICATION_UPDATE = 'ApplicationUpdate';
|
||||||
export const BACKUP = 'Backup';
|
export const BACKUP = 'Backup';
|
||||||
|
export const CLEAR_HISTORY = 'ClearHistory';
|
||||||
export const CLEAR_LOGS = 'ClearLog';
|
export const CLEAR_LOGS = 'ClearLog';
|
||||||
export const DELETE_LOG_FILES = 'DeleteLogFiles';
|
export const DELETE_LOG_FILES = 'DeleteLogFiles';
|
||||||
export const DELETE_UPDATE_LOG_FILES = 'DeleteUpdateLogFiles';
|
export const DELETE_UPDATE_LOG_FILES = 'DeleteUpdateLogFiles';
|
||||||
|
@@ -2,6 +2,7 @@ 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 FilterMenu from 'Components/Menu/FilterMenu';
|
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||||
|
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';
|
||||||
@@ -11,13 +12,40 @@ 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 translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import HistoryOptionsConnector from './HistoryOptionsConnector';
|
import HistoryOptionsConnector from './HistoryOptionsConnector';
|
||||||
import HistoryRowConnector from './HistoryRowConnector';
|
import HistoryRowConnector from './HistoryRowConnector';
|
||||||
|
|
||||||
class History extends Component {
|
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
|
// Render
|
||||||
|
|
||||||
@@ -25,9 +53,10 @@ class History extends Component {
|
|||||||
const {
|
const {
|
||||||
isFetching,
|
isFetching,
|
||||||
isPopulated,
|
isPopulated,
|
||||||
|
isHistoryClearing,
|
||||||
error,
|
error,
|
||||||
isMoviesFetching,
|
isIndexersFetching,
|
||||||
isMoviesPopulated,
|
isIndexersPopulated,
|
||||||
indexersError,
|
indexersError,
|
||||||
items,
|
items,
|
||||||
columns,
|
columns,
|
||||||
@@ -36,11 +65,12 @@ class History extends Component {
|
|||||||
totalRecords,
|
totalRecords,
|
||||||
onFilterSelect,
|
onFilterSelect,
|
||||||
onFirstPagePress,
|
onFirstPagePress,
|
||||||
|
onClearHistoryPress,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const isFetchingAny = isFetching || isMoviesFetching;
|
const isFetchingAny = isFetching || isIndexersFetching;
|
||||||
const isAllPopulated = isPopulated && (isMoviesPopulated || !items.length);
|
const isAllPopulated = isPopulated && (isIndexersPopulated || !items.length);
|
||||||
const hasError = error || indexersError;
|
const hasError = error || indexersError;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -53,6 +83,12 @@ class History extends Component {
|
|||||||
isSpinning={isFetching}
|
isSpinning={isFetching}
|
||||||
onPress={onFirstPagePress}
|
onPress={onFirstPagePress}
|
||||||
/>
|
/>
|
||||||
|
<PageToolbarButton
|
||||||
|
label={translate('Clear')}
|
||||||
|
iconName={icons.DELETE}
|
||||||
|
isSpinning={isHistoryClearing}
|
||||||
|
onPress={this.onClearHistoryPress}
|
||||||
|
/>
|
||||||
</PageToolbarSection>
|
</PageToolbarSection>
|
||||||
|
|
||||||
<PageToolbarSection alignContent={align.RIGHT}>
|
<PageToolbarSection alignContent={align.RIGHT}>
|
||||||
@@ -131,6 +167,16 @@ class History extends Component {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
|
|
||||||
|
<ConfirmModal
|
||||||
|
isOpen={this.state.isClearHistoryModalOpen}
|
||||||
|
kind={kinds.DANGER}
|
||||||
|
title={translate('ClearHistory')}
|
||||||
|
message={translate('ClearHistoryMessageText')}
|
||||||
|
confirmLabel={translate('Delete')}
|
||||||
|
onConfirm={this.onConfirmClearHistory}
|
||||||
|
onCancel={this.onClearHistoryModalClose}
|
||||||
|
/>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -139,9 +185,10 @@ class History extends Component {
|
|||||||
History.propTypes = {
|
History.propTypes = {
|
||||||
isFetching: PropTypes.bool.isRequired,
|
isFetching: PropTypes.bool.isRequired,
|
||||||
isPopulated: PropTypes.bool.isRequired,
|
isPopulated: PropTypes.bool.isRequired,
|
||||||
|
isHistoryClearing: PropTypes.bool.isRequired,
|
||||||
error: PropTypes.object,
|
error: PropTypes.object,
|
||||||
isMoviesFetching: PropTypes.bool.isRequired,
|
isIndexersFetching: PropTypes.bool.isRequired,
|
||||||
isMoviesPopulated: PropTypes.bool.isRequired,
|
isIndexersPopulated: PropTypes.bool.isRequired,
|
||||||
indexersError: PropTypes.object,
|
indexersError: PropTypes.object,
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
@@ -149,7 +196,8 @@ History.propTypes = {
|
|||||||
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
totalRecords: PropTypes.number,
|
totalRecords: PropTypes.number,
|
||||||
onFilterSelect: PropTypes.func.isRequired,
|
onFilterSelect: PropTypes.func.isRequired,
|
||||||
onFirstPagePress: PropTypes.func.isRequired
|
onFirstPagePress: PropTypes.func.isRequired,
|
||||||
|
onClearHistoryPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default History;
|
export default History;
|
||||||
|
@@ -2,8 +2,11 @@ import PropTypes from 'prop-types';
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
import * as commandNames from 'Commands/commandNames';
|
||||||
import withCurrentPage from 'Components/withCurrentPage';
|
import withCurrentPage from 'Components/withCurrentPage';
|
||||||
|
import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
import * as historyActions from 'Store/Actions/historyActions';
|
import * as historyActions from 'Store/Actions/historyActions';
|
||||||
|
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||||
import History from './History';
|
import History from './History';
|
||||||
|
|
||||||
@@ -11,11 +14,13 @@ function createMapStateToProps() {
|
|||||||
return createSelector(
|
return createSelector(
|
||||||
(state) => state.history,
|
(state) => state.history,
|
||||||
(state) => state.indexers,
|
(state) => state.indexers,
|
||||||
(history, indexers) => {
|
createCommandExecutingSelector(commandNames.CLEAR_HISTORY),
|
||||||
|
(history, indexers, isHistoryClearing) => {
|
||||||
return {
|
return {
|
||||||
isMoviesFetching: indexers.isFetching,
|
isIndexersFetching: indexers.isFetching,
|
||||||
isMoviesPopulated: indexers.isPopulated,
|
isIndexersPopulated: indexers.isPopulated,
|
||||||
indexersError: indexers.error,
|
indexersError: indexers.error,
|
||||||
|
isHistoryClearing,
|
||||||
...history
|
...history
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -23,6 +28,7 @@ function createMapStateToProps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
|
executeCommand,
|
||||||
...historyActions
|
...historyActions
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,6 +53,12 @@ class HistoryConnector extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.isHistoryClearing && !this.props.isHistoryClearing) {
|
||||||
|
this.props.gotoHistoryFirstPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
unregisterPagePopulator(this.repopulate);
|
unregisterPagePopulator(this.repopulate);
|
||||||
this.props.clearHistory();
|
this.props.clearHistory();
|
||||||
@@ -90,6 +102,10 @@ class HistoryConnector extends Component {
|
|||||||
this.props.setHistoryFilter({ selectedFilterKey });
|
this.props.setHistoryFilter({ selectedFilterKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClearHistoryPress = () => {
|
||||||
|
this.props.executeCommand({ name: commandNames.CLEAR_HISTORY });
|
||||||
|
}
|
||||||
|
|
||||||
onTableOptionChange = (payload) => {
|
onTableOptionChange = (payload) => {
|
||||||
this.props.setHistoryTableOption(payload);
|
this.props.setHistoryTableOption(payload);
|
||||||
|
|
||||||
@@ -112,6 +128,7 @@ class HistoryConnector extends Component {
|
|||||||
onSortPress={this.onSortPress}
|
onSortPress={this.onSortPress}
|
||||||
onFilterSelect={this.onFilterSelect}
|
onFilterSelect={this.onFilterSelect}
|
||||||
onTableOptionChange={this.onTableOptionChange}
|
onTableOptionChange={this.onTableOptionChange}
|
||||||
|
onClearHistoryPress={this.onClearHistoryPress}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -122,6 +139,8 @@ HistoryConnector.propTypes = {
|
|||||||
useCurrentPage: PropTypes.bool.isRequired,
|
useCurrentPage: PropTypes.bool.isRequired,
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
fetchHistory: PropTypes.func.isRequired,
|
fetchHistory: PropTypes.func.isRequired,
|
||||||
|
clearHistory: PropTypes.func.isRequired,
|
||||||
|
isHistoryClearing: PropTypes.bool.isRequired,
|
||||||
gotoHistoryFirstPage: PropTypes.func.isRequired,
|
gotoHistoryFirstPage: PropTypes.func.isRequired,
|
||||||
gotoHistoryPreviousPage: PropTypes.func.isRequired,
|
gotoHistoryPreviousPage: PropTypes.func.isRequired,
|
||||||
gotoHistoryNextPage: PropTypes.func.isRequired,
|
gotoHistoryNextPage: PropTypes.func.isRequired,
|
||||||
@@ -130,7 +149,7 @@ HistoryConnector.propTypes = {
|
|||||||
setHistorySort: PropTypes.func.isRequired,
|
setHistorySort: PropTypes.func.isRequired,
|
||||||
setHistoryFilter: PropTypes.func.isRequired,
|
setHistoryFilter: PropTypes.func.isRequired,
|
||||||
setHistoryTableOption: PropTypes.func.isRequired,
|
setHistoryTableOption: PropTypes.func.isRequired,
|
||||||
clearHistory: PropTypes.func.isRequired
|
executeCommand: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withCurrentPage(
|
export default withCurrentPage(
|
||||||
|
@@ -51,8 +51,6 @@ class HistoryRow extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(categories);
|
|
||||||
|
|
||||||
this.props.onSearchPress(data.query, indexer.id, categories);
|
this.props.onSearchPress(data.query, indexer.id, categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,6 @@ class SearchFooterConnector extends Component {
|
|||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onInputChange = ({ name, value }) => {
|
onInputChange = ({ name, value }) => {
|
||||||
console.log(name, value);
|
|
||||||
this.props.setSearchDefault({ [name]: value });
|
this.props.setSearchDefault({ [name]: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -108,7 +108,6 @@ export const defaultState = {
|
|||||||
|
|
||||||
sortPredicates: {
|
sortPredicates: {
|
||||||
age: function(item) {
|
age: function(item) {
|
||||||
console.log(item);
|
|
||||||
return item.ageMinutes;
|
return item.ageMinutes;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.History
|
||||||
|
{
|
||||||
|
public class ClearHistoryCommand : Command
|
||||||
|
{
|
||||||
|
public override bool SendUpdatesToClient => true;
|
||||||
|
}
|
||||||
|
}
|
@@ -31,7 +31,8 @@ namespace NzbDrone.Core.History
|
|||||||
IHandle<IndexerQueryEvent>,
|
IHandle<IndexerQueryEvent>,
|
||||||
IHandle<IndexerDownloadEvent>,
|
IHandle<IndexerDownloadEvent>,
|
||||||
IHandle<IndexerAuthEvent>,
|
IHandle<IndexerAuthEvent>,
|
||||||
IExecute<CleanUpHistoryCommand>
|
IExecute<CleanUpHistoryCommand>,
|
||||||
|
IExecute<ClearHistoryCommand>
|
||||||
{
|
{
|
||||||
private readonly IHistoryRepository _historyRepository;
|
private readonly IHistoryRepository _historyRepository;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
@@ -197,5 +198,10 @@ namespace NzbDrone.Core.History
|
|||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Execute(ClearHistoryCommand message)
|
||||||
|
{
|
||||||
|
_historyRepository.Purge(vacuum: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,6 +47,8 @@
|
|||||||
"CertificateValidationHelpText": "Change how strict HTTPS certification validation is",
|
"CertificateValidationHelpText": "Change how strict HTTPS certification validation is",
|
||||||
"ChangeHasNotBeenSavedYet": "Change has not been saved yet",
|
"ChangeHasNotBeenSavedYet": "Change has not been saved yet",
|
||||||
"Clear": "Clear",
|
"Clear": "Clear",
|
||||||
|
"ClearHistory": "Clear History",
|
||||||
|
"ClearHistoryMessageText": "Are you sure you want to clear all Prowlarr history?",
|
||||||
"ClientPriority": "Client Priority",
|
"ClientPriority": "Client Priority",
|
||||||
"CloneIndexer": "Clone Indexer",
|
"CloneIndexer": "Clone Indexer",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
Reference in New Issue
Block a user