mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-26 22:46:53 -04:00
New: Monitor and Process downloads separately
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
This commit is contained in:
@@ -51,7 +51,7 @@ class Queue extends Component {
|
||||
|
||||
const selectedIds = this.getSelectedIds();
|
||||
const isPendingSelected = _.some(this.props.items, (item) => {
|
||||
return selectedIds.indexOf(item.id) > -1 && item.status === 'Delay';
|
||||
return selectedIds.indexOf(item.id) > -1 && item.status === 'delay';
|
||||
});
|
||||
|
||||
if (isPendingSelected !== this.state.isPendingSelected) {
|
||||
@@ -87,8 +87,8 @@ class Queue extends Component {
|
||||
this.setState({ isConfirmRemoveModalOpen: true });
|
||||
}
|
||||
|
||||
onRemoveSelectedConfirmed = (blacklist) => {
|
||||
this.props.onRemoveSelectedPress(this.getSelectedIds(), blacklist);
|
||||
onRemoveSelectedConfirmed = (payload) => {
|
||||
this.props.onRemoveSelectedPress({ ids: this.getSelectedIds(), ...payload });
|
||||
this.setState({ isConfirmRemoveModalOpen: false });
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ class Queue extends Component {
|
||||
totalRecords,
|
||||
isGrabbing,
|
||||
isRemoving,
|
||||
isCheckForFinishedDownloadExecuting,
|
||||
isRefreshMonitoredDownloadsExecuting,
|
||||
onRefreshPress,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
@@ -125,10 +125,11 @@ class Queue extends Component {
|
||||
isPendingSelected
|
||||
} = this.state;
|
||||
|
||||
const isRefreshing = isFetching || isMoviesFetching || isCheckForFinishedDownloadExecuting;
|
||||
const isRefreshing = isFetching || isMoviesFetching || isRefreshMonitoredDownloadsExecuting;
|
||||
const isAllPopulated = isPopulated && (isMoviesPopulated || !items.length || items.every((e) => !e.movieId));
|
||||
const hasError = error || moviesError;
|
||||
const selectedCount = this.getSelectedIds().length;
|
||||
const selectedIds = this.getSelectedIds();
|
||||
const selectedCount = selectedIds.length;
|
||||
const disableSelectedActions = selectedCount === 0;
|
||||
|
||||
return (
|
||||
@@ -239,6 +240,13 @@ class Queue extends Component {
|
||||
<RemoveQueueItemsModal
|
||||
isOpen={isConfirmRemoveModalOpen}
|
||||
selectedCount={selectedCount}
|
||||
canIgnore={isConfirmRemoveModalOpen && (
|
||||
selectedIds.every((id) => {
|
||||
const item = items.find((i) => i.id === id);
|
||||
|
||||
return !!(item && item.movieId);
|
||||
})
|
||||
)}
|
||||
onRemovePress={this.onRemoveSelectedConfirmed}
|
||||
onModalClose={this.onConfirmRemoveModalClose}
|
||||
/>
|
||||
@@ -259,7 +267,7 @@ Queue.propTypes = {
|
||||
totalRecords: PropTypes.number,
|
||||
isGrabbing: PropTypes.bool.isRequired,
|
||||
isRemoving: PropTypes.bool.isRequired,
|
||||
isCheckForFinishedDownloadExecuting: PropTypes.bool.isRequired,
|
||||
isRefreshMonitoredDownloadsExecuting: PropTypes.bool.isRequired,
|
||||
onRefreshPress: PropTypes.func.isRequired,
|
||||
onGrabSelectedPress: PropTypes.func.isRequired,
|
||||
onRemoveSelectedPress: PropTypes.func.isRequired
|
||||
|
||||
@@ -15,13 +15,13 @@ function createMapStateToProps() {
|
||||
(state) => state.movies,
|
||||
(state) => state.queue.options,
|
||||
(state) => state.queue.paged,
|
||||
createCommandExecutingSelector(commandNames.CHECK_FOR_FINISHED_DOWNLOAD),
|
||||
(movies, options, queue, isCheckForFinishedDownloadExecuting) => {
|
||||
createCommandExecutingSelector(commandNames.REFRESH_MONITORED_DOWNLOADS),
|
||||
(movies, options, queue, isRefreshMonitoredDownloadsExecuting) => {
|
||||
return {
|
||||
isMoviesFetching: movies.isFetching,
|
||||
isMoviesPopulated: movies.isPopulated,
|
||||
moviesError: movies.error,
|
||||
isCheckForFinishedDownloadExecuting,
|
||||
isRefreshMonitoredDownloadsExecuting,
|
||||
...options,
|
||||
...queue
|
||||
};
|
||||
@@ -113,7 +113,7 @@ class QueueConnector extends Component {
|
||||
|
||||
onRefreshPress = () => {
|
||||
this.props.executeCommand({
|
||||
name: commandNames.CHECK_FOR_FINISHED_DOWNLOAD
|
||||
name: commandNames.REFRESH_MONITORED_DOWNLOADS
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ class QueueConnector extends Component {
|
||||
this.props.grabQueueItems({ ids });
|
||||
}
|
||||
|
||||
onRemoveSelectedPress = (ids, blacklist) => {
|
||||
this.props.removeQueueItems({ ids, blacklist });
|
||||
onRemoveSelectedPress = (payload) => {
|
||||
this.props.removeQueueItems(payload);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -68,6 +68,7 @@ class QueueRow extends Component {
|
||||
title,
|
||||
status,
|
||||
trackedDownloadStatus,
|
||||
trackedDownloadState,
|
||||
statusMessages,
|
||||
errorMessage,
|
||||
movie,
|
||||
@@ -100,8 +101,8 @@ class QueueRow extends Component {
|
||||
} = this.state;
|
||||
|
||||
const progress = 100 - (sizeleft / size * 100);
|
||||
const showInteractiveImport = status === 'Completed' && trackedDownloadStatus === 'Warning';
|
||||
const isPending = status === 'Delay' || status === 'DownloadClientUnavailable';
|
||||
const showInteractiveImport = status === 'completed' && trackedDownloadStatus === 'warning';
|
||||
const isPending = status === 'delay' || status === 'downloadClientUnavailable';
|
||||
|
||||
return (
|
||||
<TableRow>
|
||||
@@ -129,6 +130,7 @@ class QueueRow extends Component {
|
||||
sourceTitle={title}
|
||||
status={status}
|
||||
trackedDownloadStatus={trackedDownloadStatus}
|
||||
trackedDownloadState={trackedDownloadState}
|
||||
statusMessages={statusMessages}
|
||||
errorMessage={errorMessage}
|
||||
/>
|
||||
@@ -315,6 +317,7 @@ class QueueRow extends Component {
|
||||
<RemoveQueueItemModal
|
||||
isOpen={isRemoveQueueItemModalOpen}
|
||||
sourceTitle={title}
|
||||
canIgnore={!!(movie)}
|
||||
onRemovePress={this.onRemoveQueueItemModalConfirmed}
|
||||
onModalClose={this.onRemoveQueueItemModalClose}
|
||||
/>
|
||||
@@ -330,6 +333,7 @@ QueueRow.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
trackedDownloadStatus: PropTypes.string,
|
||||
trackedDownloadState: PropTypes.string,
|
||||
statusMessages: PropTypes.arrayOf(PropTypes.object),
|
||||
errorMessage: PropTypes.string,
|
||||
movie: PropTypes.object,
|
||||
|
||||
@@ -39,8 +39,8 @@ class QueueRowConnector extends Component {
|
||||
this.props.grabQueueItem({ id: this.props.id });
|
||||
}
|
||||
|
||||
onRemoveQueueItemPress = (blacklist) => {
|
||||
this.props.removeQueueItem({ id: this.props.id, blacklist });
|
||||
onRemoveQueueItemPress = (payload) => {
|
||||
this.props.removeQueueItem({ id: this.props.id, ...payload });
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -37,13 +37,14 @@ function QueueStatusCell(props) {
|
||||
const {
|
||||
sourceTitle,
|
||||
status,
|
||||
trackedDownloadStatus = 'Ok',
|
||||
trackedDownloadStatus,
|
||||
trackedDownloadState,
|
||||
statusMessages,
|
||||
errorMessage
|
||||
} = props;
|
||||
|
||||
const hasWarning = trackedDownloadStatus === 'Warning';
|
||||
const hasError = trackedDownloadStatus === 'Error';
|
||||
const hasWarning = trackedDownloadStatus === 'warning';
|
||||
const hasError = trackedDownloadStatus === 'error';
|
||||
|
||||
// status === 'downloading'
|
||||
let iconName = icons.DOWNLOADING;
|
||||
@@ -54,22 +55,34 @@ function QueueStatusCell(props) {
|
||||
iconKind = kinds.WARNING;
|
||||
}
|
||||
|
||||
if (status === 'Paused') {
|
||||
if (status === 'paused') {
|
||||
iconName = icons.PAUSED;
|
||||
title = 'Paused';
|
||||
}
|
||||
|
||||
if (status === 'Queued') {
|
||||
if (status === 'queued') {
|
||||
iconName = icons.QUEUED;
|
||||
title = 'Queued';
|
||||
}
|
||||
|
||||
if (status === 'Completed') {
|
||||
if (status === 'completed') {
|
||||
iconName = icons.DOWNLOADED;
|
||||
title = 'Downloaded';
|
||||
|
||||
if (trackedDownloadState === 'importPending') {
|
||||
title += ' - Waiting to Import';
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'importing') {
|
||||
title += ' - Importing';
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'failedPending') {
|
||||
title += ' - Waiting to Process';
|
||||
}
|
||||
}
|
||||
|
||||
if (status === 'Delay') {
|
||||
if (status === 'delay') {
|
||||
iconName = icons.PENDING;
|
||||
title = 'Pending';
|
||||
}
|
||||
@@ -80,20 +93,20 @@ function QueueStatusCell(props) {
|
||||
title = 'Pending - Download client is unavailable';
|
||||
}
|
||||
|
||||
if (status === 'Failed') {
|
||||
if (status === 'failed') {
|
||||
iconName = icons.DOWNLOADING;
|
||||
iconKind = kinds.DANGER;
|
||||
title = 'Download failed';
|
||||
}
|
||||
|
||||
if (status === 'Warning') {
|
||||
if (status === 'warning') {
|
||||
iconName = icons.DOWNLOADING;
|
||||
iconKind = kinds.WARNING;
|
||||
title = `Download warning: ${errorMessage || 'check download client for more details'}`;
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
if (status === 'Completed') {
|
||||
if (status === 'completed') {
|
||||
iconName = icons.DOWNLOAD;
|
||||
iconKind = kinds.DANGER;
|
||||
title = `Import failed: ${sourceTitle}`;
|
||||
@@ -125,9 +138,15 @@ function QueueStatusCell(props) {
|
||||
QueueStatusCell.propTypes = {
|
||||
sourceTitle: PropTypes.string.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
trackedDownloadStatus: PropTypes.string,
|
||||
trackedDownloadStatus: PropTypes.string.isRequired,
|
||||
trackedDownloadState: PropTypes.string.isRequired,
|
||||
statusMessages: PropTypes.arrayOf(PropTypes.object),
|
||||
errorMessage: PropTypes.string
|
||||
};
|
||||
|
||||
QueueStatusCell.defaultProps = {
|
||||
trackedDownloadStatus: 'Ok',
|
||||
trackedDownloadState: 'Downloading'
|
||||
};
|
||||
|
||||
export default QueueStatusCell;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
.messageRemove {
|
||||
margin-bottom: 30px;
|
||||
color: $dangerColor;
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import styles from './RemoveQueueItemModal.css';
|
||||
|
||||
class RemoveQueueItemModal extends Component {
|
||||
|
||||
@@ -21,26 +20,41 @@ class RemoveQueueItemModal extends Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
remove: true,
|
||||
blacklist: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Control
|
||||
|
||||
resetState = function() {
|
||||
this.setState({
|
||||
remove: true,
|
||||
blacklist: false
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onRemoveChange = ({ value }) => {
|
||||
this.setState({ remove: value });
|
||||
}
|
||||
|
||||
onBlacklistChange = ({ value }) => {
|
||||
this.setState({ blacklist: value });
|
||||
}
|
||||
|
||||
onRemoveQueueItemConfirmed = () => {
|
||||
const blacklist = this.state.blacklist;
|
||||
onRemoveConfirmed = () => {
|
||||
const state = this.state;
|
||||
|
||||
this.setState({ blacklist: false });
|
||||
this.props.onRemovePress(blacklist);
|
||||
this.resetState();
|
||||
this.props.onRemovePress(state);
|
||||
}
|
||||
|
||||
onModalClose = () => {
|
||||
this.setState({ blacklist: false });
|
||||
this.resetState();
|
||||
this.props.onModalClose();
|
||||
}
|
||||
|
||||
@@ -50,10 +64,11 @@ class RemoveQueueItemModal extends Component {
|
||||
render() {
|
||||
const {
|
||||
isOpen,
|
||||
sourceTitle
|
||||
sourceTitle,
|
||||
canIgnore
|
||||
} = this.props;
|
||||
|
||||
const blacklist = this.state.blacklist;
|
||||
const { remove, blacklist } = this.state;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -73,9 +88,18 @@ class RemoveQueueItemModal extends Component {
|
||||
Are you sure you want to remove '{sourceTitle}' from the queue?
|
||||
</div>
|
||||
|
||||
<div className={styles.messageRemove}>
|
||||
Removing will remove the download and the file(s) from the download client.
|
||||
</div>
|
||||
<FormGroup>
|
||||
<FormLabel>Remove From Download Client</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Blacklist Release</FormLabel>
|
||||
@@ -83,7 +107,7 @@ class RemoveQueueItemModal extends Component {
|
||||
type={inputTypes.CHECK}
|
||||
name="blacklist"
|
||||
value={blacklist}
|
||||
helpText="Prevents Radarr from automatically grabbing this movie again"
|
||||
helpText="Starts a search for this movie again and prevents this release from being grabbed again"
|
||||
onChange={this.onBlacklistChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -97,7 +121,7 @@ class RemoveQueueItemModal extends Component {
|
||||
|
||||
<Button
|
||||
kind={kinds.DANGER}
|
||||
onPress={this.onRemoveQueueItemConfirmed}
|
||||
onPress={this.onRemoveConfirmed}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
@@ -111,6 +135,7 @@ class RemoveQueueItemModal extends Component {
|
||||
RemoveQueueItemModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
sourceTitle: PropTypes.string.isRequired,
|
||||
canIgnore: PropTypes.bool.isRequired,
|
||||
onRemovePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -21,26 +21,41 @@ class RemoveQueueItemsModal extends Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
remove: true,
|
||||
blacklist: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
// Control
|
||||
|
||||
resetState = function() {
|
||||
this.setState({
|
||||
remove: true,
|
||||
blacklist: false
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onRemoveChange = ({ value }) => {
|
||||
this.setState({ remove: value });
|
||||
}
|
||||
|
||||
onBlacklistChange = ({ value }) => {
|
||||
this.setState({ blacklist: value });
|
||||
}
|
||||
|
||||
onRemoveQueueItemConfirmed = () => {
|
||||
const blacklist = this.state.blacklist;
|
||||
onRemoveConfirmed = () => {
|
||||
const state = this.state;
|
||||
|
||||
this.setState({ blacklist: false });
|
||||
this.props.onRemovePress(blacklist);
|
||||
this.resetState();
|
||||
this.props.onRemovePress(state);
|
||||
}
|
||||
|
||||
onModalClose = () => {
|
||||
this.setState({ blacklist: false });
|
||||
this.resetState();
|
||||
this.props.onModalClose();
|
||||
}
|
||||
|
||||
@@ -50,10 +65,11 @@ class RemoveQueueItemsModal extends Component {
|
||||
render() {
|
||||
const {
|
||||
isOpen,
|
||||
selectedCount
|
||||
selectedCount,
|
||||
canIgnore
|
||||
} = this.props;
|
||||
|
||||
const blacklist = this.state.blacklist;
|
||||
const { remove, blacklist } = this.state;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -74,12 +90,28 @@ class RemoveQueueItemsModal extends Component {
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Blacklist Release</FormLabel>
|
||||
<FormLabel>Remove From Download Client</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
Blacklist Release{selectedCount > 1 ? 's' : ''}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="blacklist"
|
||||
value={blacklist}
|
||||
helpText="Prevents Radarr from automatically grabbing this release again"
|
||||
helpText="Prevents Radarr from automatically grabbing this movie again"
|
||||
onChange={this.onBlacklistChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -93,7 +125,7 @@ class RemoveQueueItemsModal extends Component {
|
||||
|
||||
<Button
|
||||
kind={kinds.DANGER}
|
||||
onPress={this.onRemoveQueueItemConfirmed}
|
||||
onPress={this.onRemoveConfirmed}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
@@ -107,6 +139,7 @@ class RemoveQueueItemsModal extends Component {
|
||||
RemoveQueueItemsModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
selectedCount: PropTypes.number.isRequired,
|
||||
canIgnore: PropTypes.bool.isRequired,
|
||||
onRemovePress: PropTypes.func.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user