You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Lidarr/frontend/src/Activity/Queue/QueueRow.js

465 lines
13 KiB

import PropTypes from 'prop-types';
import React, { Component } from 'react';
4 years ago
import ProtocolLabel from 'Activity/Queue/ProtocolLabel';
import AlbumFormats from 'Album/AlbumFormats';
4 years ago
import AlbumTitleLink from 'Album/AlbumTitleLink';
import TrackQuality from 'Album/TrackQuality';
import ArtistNameLink from 'Artist/ArtistNameLink';
import Icon from 'Components/Icon';
import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import ProgressBar from 'Components/ProgressBar';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
4 years ago
import TableRow from 'Components/Table/TableRow';
import Popover from 'Components/Tooltip/Popover';
import Tooltip from 'Components/Tooltip/Tooltip';
4 years ago
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
import formatBytes from 'Utilities/Number/formatBytes';
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
import translate from 'Utilities/String/translate';
import QueueStatusCell from './QueueStatusCell';
import RemoveQueueItemModal from './RemoveQueueItemModal';
4 years ago
import TimeleftCell from './TimeleftCell';
import styles from './QueueRow.css';
class QueueRow extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
isRemoveQueueItemModalOpen: false,
isInteractiveImportModalOpen: false
};
}
//
// Listeners
onRemoveQueueItemPress = () => {
this.setState({ isRemoveQueueItemModalOpen: true });
};
onRemoveQueueItemModalConfirmed = (blocklist, skipRedownload) => {
const {
onRemoveQueueItemPress,
onQueueRowModalOpenOrClose
} = this.props;
onQueueRowModalOpenOrClose(false);
onRemoveQueueItemPress(blocklist, skipRedownload);
this.setState({ isRemoveQueueItemModalOpen: false });
};
onRemoveQueueItemModalClose = () => {
this.props.onQueueRowModalOpenOrClose(false);
this.setState({ isRemoveQueueItemModalOpen: false });
};
onInteractiveImportPress = () => {
this.props.onQueueRowModalOpenOrClose(true);
this.setState({ isInteractiveImportModalOpen: true });
};
onInteractiveImportModalClose = () => {
this.props.onQueueRowModalOpenOrClose(false);
this.setState({ isInteractiveImportModalOpen: false });
};
//
// Render
render() {
const {
id,
downloadId,
title,
status,
trackedDownloadStatus,
trackedDownloadState,
statusMessages,
errorMessage,
7 years ago
artist,
album,
quality,
customFormats,
customFormatScore,
protocol,
indexer,
outputPath,
downloadClient,
downloadClientHasPostImportCategory,
downloadForced,
estimatedCompletionTime,
added,
timeleft,
size,
sizeleft,
showRelativeDates,
shortDateFormat,
timeFormat,
isGrabbing,
grabError,
isRemoving,
isSelected,
columns,
onSelectedChange,
onGrabPress
} = this.props;
const {
isRemoveQueueItemModalOpen,
isInteractiveImportModalOpen
} = this.state;
const progress = 100 - (sizeleft / size * 100);
const showInteractiveImport = status === 'completed' && trackedDownloadStatus === 'warning';
const isPending = status === 'delay' || status === 'downloadClientUnavailable';
return (
<TableRow>
<TableSelectCell
id={id}
isSelected={isSelected}
onSelectedChange={onSelectedChange}
/>
{
columns.map((column) => {
const {
name,
isVisible
} = column;
if (!isVisible) {
return null;
}
if (name === 'status') {
return (
<QueueStatusCell
key={name}
sourceTitle={title}
status={status}
trackedDownloadStatus={trackedDownloadStatus}
trackedDownloadState={trackedDownloadState}
statusMessages={statusMessages}
errorMessage={errorMessage}
/>
);
}
if (name === 'artists.sortName') {
return (
<TableRowCell key={name}>
{
artist ?
<ArtistNameLink
foreignArtistId={artist.foreignArtistId}
artistName={artist.artistName}
/> :
title
}
</TableRowCell>
);
}
if (name === 'albums.title') {
return (
<TableRowCell key={name}>
{
album ?
<AlbumTitleLink
foreignAlbumId={album.foreignAlbumId}
title={album.title}
disambiguation={album.disambiguation}
/> :
'-'
}
</TableRowCell>
);
}
if (name === 'albums.releaseDate') {
if (album) {
return (
<RelativeDateCellConnector
key={name}
date={album.releaseDate}
/>
);
}
return (
<TableRowCell key={name}>
-
</TableRowCell>
);
}
if (name === 'quality') {
return (
<TableRowCell key={name}>
{
quality ?
<TrackQuality
quality={quality}
/> :
null
}
</TableRowCell>
);
}
if (name === 'customFormats') {
return (
<TableRowCell key={name}>
<AlbumFormats
formats={customFormats}
/>
</TableRowCell>
);
}
if (name === 'customFormatScore') {
return (
<TableRowCell
key={name}
className={styles.customFormatScore}
>
<Tooltip
anchor={formatCustomFormatScore(
customFormatScore,
customFormats.length
)}
tooltip={<AlbumFormats formats={customFormats} />}
position={tooltipPositions.BOTTOM}
/>
</TableRowCell>
);
}
if (name === 'protocol') {
return (
<TableRowCell key={name}>
<ProtocolLabel
protocol={protocol}
/>
</TableRowCell>
);
}
if (name === 'indexer') {
return (
<TableRowCell key={name}>
{indexer}
</TableRowCell>
);
}
if (name === 'downloadClient') {
return (
<TableRowCell key={name}>
{downloadClient}
</TableRowCell>
);
}
if (name === 'title') {
return (
<TableRowCell key={name}>
{title}
</TableRowCell>
);
}
if (name === 'size') {
return (
<TableRowCell key={name}>{formatBytes(size)}</TableRowCell>
);
}
if (name === 'outputPath') {
return (
<TableRowCell key={name}>
{outputPath}
</TableRowCell>
);
}
if (name === 'estimatedCompletionTime') {
return (
<TimeleftCell
key={name}
status={status}
estimatedCompletionTime={estimatedCompletionTime}
timeleft={timeleft}
size={size}
sizeleft={sizeleft}
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
timeFormat={timeFormat}
/>
);
}
if (name === 'progress') {
return (
<TableRowCell
key={name}
className={styles.progress}
>
{
!!progress &&
<ProgressBar
progress={progress}
title={`${progress.toFixed(1)}%`}
/>
}
</TableRowCell>
);
}
if (name === 'added') {
return (
<RelativeDateCellConnector
key={name}
date={added}
/>
);
}
if (name === 'actions') {
return (
<TableRowCell
key={name}
className={styles.actions}
>
{
downloadForced &&
<Popover
anchor={
<Icon
name={icons.DANGER}
kind={kinds.DANGER}
/>
}
title={translate('ManualDownload')}
body="This release failed parsing checks and was manually downloaded from an interactive search. Import is likely to fail."
position={tooltipPositions.LEFT}
/>
}
{
showInteractiveImport &&
<IconButton
name={icons.INTERACTIVE}
onPress={this.onInteractiveImportPress}
/>
}
{
isPending &&
<SpinnerIconButton
name={icons.DOWNLOAD}
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
isSpinning={isGrabbing}
onPress={onGrabPress}
/>
}
<SpinnerIconButton
title={translate('RemoveFromQueue')}
name={icons.REMOVE}
isSpinning={isRemoving}
onPress={this.onRemoveQueueItemPress}
/>
</TableRowCell>
);
}
return null;
})
}
<InteractiveImportModal
isOpen={isInteractiveImportModalOpen}
downloadId={downloadId}
title={title}
onModalClose={this.onInteractiveImportModalClose}
showReplaceExistingFiles={true}
replaceExistingFiles={true}
/>
<RemoveQueueItemModal
isOpen={isRemoveQueueItemModalOpen}
sourceTitle={title}
canChangeCategory={!!downloadClientHasPostImportCategory}
canIgnore={!!artist}
isPending={isPending}
onRemovePress={this.onRemoveQueueItemModalConfirmed}
onModalClose={this.onRemoveQueueItemModalClose}
/>
</TableRow>
);
}
}
QueueRow.propTypes = {
id: PropTypes.number.isRequired,
downloadId: PropTypes.string,
title: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
trackedDownloadStatus: PropTypes.string,
trackedDownloadState: PropTypes.string,
statusMessages: PropTypes.arrayOf(PropTypes.object),
errorMessage: PropTypes.string,
artist: PropTypes.object,
album: PropTypes.object,
quality: PropTypes.object.isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object),
customFormatScore: PropTypes.number.isRequired,
protocol: PropTypes.string.isRequired,
indexer: PropTypes.string,
outputPath: PropTypes.string,
downloadClient: PropTypes.string,
downloadClientHasPostImportCategory: PropTypes.bool,
downloadForced: PropTypes.bool.isRequired,
estimatedCompletionTime: PropTypes.string,
added: PropTypes.string,
timeleft: PropTypes.string,
size: PropTypes.number,
sizeleft: PropTypes.number,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
isGrabbing: PropTypes.bool.isRequired,
grabError: PropTypes.object,
isRemoving: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
onSelectedChange: PropTypes.func.isRequired,
onGrabPress: PropTypes.func.isRequired,
onRemoveQueueItemPress: PropTypes.func.isRequired,
onQueueRowModalOpenOrClose: PropTypes.func.isRequired
};
QueueRow.defaultProps = {
customFormats: [],
isGrabbing: false,
isRemoving: false
};
export default QueueRow;