mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-17 15:02:34 +02:00
Fixed: Address issues with the status being wrong color on the index and movie details (not tracking anything queued/downloading)
Fixed: Updated fetchQueueDetails() to not pass movie ids since the store doesn't use them anyways New: Added text to index poster progress bar showing status #4525 #4526 #4982
This commit is contained in:
parent
a2e8d1d5d6
commit
c51b08e26c
@ -76,16 +76,15 @@ class CalendarConnector extends Component {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (hasDifferentItems(prevProps.items, items)) {
|
if (hasDifferentItems(prevProps.items, items)) {
|
||||||
const movieIds = selectUniqueIds(items, 'id');
|
|
||||||
const movieFileIds = selectUniqueIds(items, 'movieFileId');
|
const movieFileIds = selectUniqueIds(items, 'movieFileId');
|
||||||
|
|
||||||
if (items.length) {
|
|
||||||
this.props.fetchQueueDetails({ movieIds });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movieFileIds.length) {
|
if (movieFileIds.length) {
|
||||||
this.props.fetchMovieFiles({ movieFileIds });
|
this.props.fetchMovieFiles({ movieFileIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (items.length) {
|
||||||
|
this.props.fetchQueueDetails();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevProps.time !== time) {
|
if (prevProps.time !== time) {
|
||||||
|
@ -87,6 +87,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
border-color: $queueColor;
|
||||||
|
background-color: $queueColor;
|
||||||
|
|
||||||
|
&.outline {
|
||||||
|
color: $queueColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Sizes **/
|
/** Sizes **/
|
||||||
|
|
||||||
.small {
|
.small {
|
||||||
|
@ -73,6 +73,10 @@
|
|||||||
background-color: $infoColor;
|
background-color: $infoColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
background-color: $queueColor;
|
||||||
|
}
|
||||||
|
|
||||||
.small {
|
.small {
|
||||||
height: $progressBarSmallHeight;
|
height: $progressBarSmallHeight;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ export const PRIMARY = 'primary';
|
|||||||
export const PURPLE = 'purple';
|
export const PURPLE = 'purple';
|
||||||
export const SUCCESS = 'success';
|
export const SUCCESS = 'success';
|
||||||
export const WARNING = 'warning';
|
export const WARNING = 'warning';
|
||||||
|
export const QUEUE = 'queue';
|
||||||
|
|
||||||
export const all = [
|
export const all = [
|
||||||
DANGER,
|
DANGER,
|
||||||
@ -19,5 +20,6 @@ export const all = [
|
|||||||
PRIMARY,
|
PRIMARY,
|
||||||
PURPLE,
|
PURPLE,
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
WARNING
|
WARNING,
|
||||||
|
QUEUE
|
||||||
];
|
];
|
||||||
|
@ -267,6 +267,7 @@ class MovieDetails extends Component {
|
|||||||
onMonitorTogglePress,
|
onMonitorTogglePress,
|
||||||
onRefreshPress,
|
onRefreshPress,
|
||||||
onSearchPress,
|
onSearchPress,
|
||||||
|
queueDetails,
|
||||||
movieRuntimeFormat
|
movieRuntimeFormat
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -505,6 +506,7 @@ class MovieDetails extends Component {
|
|||||||
hasMovieFiles={hasMovieFiles}
|
hasMovieFiles={hasMovieFiles}
|
||||||
monitored={monitored}
|
monitored={monitored}
|
||||||
isAvailable={isAvailable}
|
isAvailable={isAvailable}
|
||||||
|
queueDetails={queueDetails}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</InfoLabel>
|
</InfoLabel>
|
||||||
@ -774,6 +776,7 @@ MovieDetails.propTypes = {
|
|||||||
onRefreshPress: PropTypes.func.isRequired,
|
onRefreshPress: PropTypes.func.isRequired,
|
||||||
onSearchPress: PropTypes.func.isRequired,
|
onSearchPress: PropTypes.func.isRequired,
|
||||||
onGoToMovie: PropTypes.func.isRequired,
|
onGoToMovie: PropTypes.func.isRequired,
|
||||||
|
queueDetails: PropTypes.object,
|
||||||
movieRuntimeFormat: PropTypes.string.isRequired
|
movieRuntimeFormat: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,9 +87,10 @@ function createMapStateToProps() {
|
|||||||
createAllMoviesSelector(),
|
createAllMoviesSelector(),
|
||||||
createCommandsSelector(),
|
createCommandsSelector(),
|
||||||
createDimensionsSelector(),
|
createDimensionsSelector(),
|
||||||
|
(state) => state.queue.details,
|
||||||
(state) => state.app.isSidebarVisible,
|
(state) => state.app.isSidebarVisible,
|
||||||
(state) => state.settings.ui.item.movieRuntimeFormat,
|
(state) => state.settings.ui.item.movieRuntimeFormat,
|
||||||
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, isSidebarVisible, movieRuntimeFormat) => {
|
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, queueDetails, isSidebarVisible, movieRuntimeFormat) => {
|
||||||
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
|
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
|
||||||
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
|
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
|
||||||
const movie = sortedMovies[movieIndex];
|
const movie = sortedMovies[movieIndex];
|
||||||
@ -162,6 +163,7 @@ function createMapStateToProps() {
|
|||||||
nextMovie,
|
nextMovie,
|
||||||
isSmallScreen: dimensions.isSmallScreen,
|
isSmallScreen: dimensions.isSmallScreen,
|
||||||
isSidebarVisible,
|
isSidebarVisible,
|
||||||
|
queueDetails,
|
||||||
movieRuntimeFormat
|
movieRuntimeFormat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,3 +17,8 @@
|
|||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
border-left: 4px solid $warningColor;
|
border-left: 4px solid $warningColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
padding-left: 2px;
|
||||||
|
border-left: 4px solid $queueColor;
|
||||||
|
}
|
||||||
|
@ -1,36 +1,50 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import getQueueStatusText from 'Utilities/Movie/getQueueStatusText';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './MovieStatusLabel.css';
|
import styles from './MovieStatusLabel.css';
|
||||||
|
|
||||||
function getMovieStatus(hasFile, isMonitored, isAvailable) {
|
function getMovieStatus(hasFile, isMonitored, isAvailable, queueDetails = false) {
|
||||||
|
|
||||||
|
if (queueDetails.items[0]) {
|
||||||
|
const queueStatus = queueDetails.items[0].status;
|
||||||
|
const queueState = queueDetails.items[0].trackedDownloadStatus;
|
||||||
|
const queueStatusText = getQueueStatusText(queueStatus, queueState);
|
||||||
|
return queueStatusText.longText;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasFile) {
|
if (hasFile) {
|
||||||
return 'Downloaded';
|
return translate('Downloaded');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMonitored) {
|
if (!isMonitored) {
|
||||||
return 'Unmonitored';
|
return translate('Unmonitored');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAvailable && !hasFile) {
|
if (isAvailable && !hasFile) {
|
||||||
return 'Missing';
|
return translate('Missing');
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Unreleased';
|
return translate('Unreleased');
|
||||||
}
|
}
|
||||||
|
|
||||||
function MovieStatusLabel(props) {
|
function MovieStatusLabel(props) {
|
||||||
const {
|
const {
|
||||||
hasMovieFiles,
|
hasMovieFiles,
|
||||||
monitored,
|
monitored,
|
||||||
isAvailable
|
isAvailable,
|
||||||
|
queueDetails
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const status = getMovieStatus(hasMovieFiles, monitored, isAvailable);
|
const status = getMovieStatus(hasMovieFiles, monitored, isAvailable, queueDetails);
|
||||||
|
let statusClass = status;
|
||||||
|
if (queueDetails.items.length) {
|
||||||
|
statusClass = 'queue';
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={styles[status.toLowerCase()]}
|
className={styles[statusClass]}
|
||||||
>
|
>
|
||||||
{status}
|
{status}
|
||||||
</span>
|
</span>
|
||||||
@ -40,7 +54,8 @@ function MovieStatusLabel(props) {
|
|||||||
MovieStatusLabel.propTypes = {
|
MovieStatusLabel.propTypes = {
|
||||||
hasMovieFiles: PropTypes.bool.isRequired,
|
hasMovieFiles: PropTypes.bool.isRequired,
|
||||||
monitored: PropTypes.bool.isRequired,
|
monitored: PropTypes.bool.isRequired,
|
||||||
isAvailable: PropTypes.bool.isRequired
|
isAvailable: PropTypes.bool.isRequired,
|
||||||
|
queueDetails: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
MovieStatusLabel.defaultProps = {
|
MovieStatusLabel.defaultProps = {
|
||||||
|
@ -6,6 +6,7 @@ import * as commandNames from 'Commands/commandNames';
|
|||||||
import withScrollPosition from 'Components/withScrollPosition';
|
import withScrollPosition from 'Components/withScrollPosition';
|
||||||
import { executeCommand } from 'Store/Actions/commandActions';
|
import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
import { saveMovieEditor, setMovieFilter, setMovieSort, setMovieTableOption, setMovieView } from 'Store/Actions/movieIndexActions';
|
import { saveMovieEditor, setMovieFilter, setMovieSort, setMovieTableOption, setMovieView } from 'Store/Actions/movieIndexActions';
|
||||||
|
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
|
||||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||||
import scrollPositions from 'Store/scrollPositions';
|
import scrollPositions from 'Store/scrollPositions';
|
||||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||||
@ -45,6 +46,14 @@ function createMapStateToProps() {
|
|||||||
|
|
||||||
function createMapDispatchToProps(dispatch, props) {
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
return {
|
return {
|
||||||
|
fetchQueueDetails() {
|
||||||
|
dispatch(fetchQueueDetails());
|
||||||
|
},
|
||||||
|
|
||||||
|
clearQueueDetails() {
|
||||||
|
dispatch(clearQueueDetails());
|
||||||
|
},
|
||||||
|
|
||||||
dispatchFetchRootFolders() {
|
dispatchFetchRootFolders() {
|
||||||
dispatch(fetchRootFolders());
|
dispatch(fetchRootFolders());
|
||||||
},
|
},
|
||||||
@ -96,6 +105,11 @@ class MovieIndexConnector extends Component {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// TODO: Fetch root folders here for now, but should eventually fetch on editor toggle and check loaded before showing controls
|
// TODO: Fetch root folders here for now, but should eventually fetch on editor toggle and check loaded before showing controls
|
||||||
this.props.dispatchFetchRootFolders();
|
this.props.dispatchFetchRootFolders();
|
||||||
|
this.props.fetchQueueDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.clearQueueDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -134,7 +148,10 @@ MovieIndexConnector.propTypes = {
|
|||||||
view: PropTypes.string.isRequired,
|
view: PropTypes.string.isRequired,
|
||||||
dispatchFetchRootFolders: PropTypes.func.isRequired,
|
dispatchFetchRootFolders: PropTypes.func.isRequired,
|
||||||
dispatchSetMovieView: PropTypes.func.isRequired,
|
dispatchSetMovieView: PropTypes.func.isRequired,
|
||||||
dispatchSaveMovieEditor: PropTypes.func.isRequired
|
dispatchSaveMovieEditor: PropTypes.func.isRequired,
|
||||||
|
fetchQueueDetails: PropTypes.func.isRequired,
|
||||||
|
clearQueueDetails: PropTypes.func.isRequired,
|
||||||
|
items: PropTypes.arrayOf(PropTypes.object)
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withScrollPosition(
|
export default withScrollPosition(
|
||||||
|
@ -18,6 +18,12 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
composes: legendItemColor;
|
||||||
|
|
||||||
|
background-color: $queueColor;
|
||||||
|
}
|
||||||
|
|
||||||
.continuing {
|
.continuing {
|
||||||
composes: legendItemColor;
|
composes: legendItemColor;
|
||||||
|
|
||||||
|
@ -26,12 +26,6 @@ class MovieIndexFooter extends PureComponent {
|
|||||||
movieFiles += 1;
|
movieFiles += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (s.status === 'ended') {
|
|
||||||
// ended++;
|
|
||||||
// } else {
|
|
||||||
// continuing++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (s.monitored) {
|
if (s.monitored) {
|
||||||
monitored++;
|
monitored++;
|
||||||
}
|
}
|
||||||
@ -78,6 +72,13 @@ class MovieIndexFooter extends PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.legendItem}>
|
||||||
|
<div className={styles.queue} />
|
||||||
|
<div>
|
||||||
|
{translate('Queued')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={styles.legendItem}>
|
<div className={styles.legendItem}>
|
||||||
<div className={styles.continuing} />
|
<div className={styles.continuing} />
|
||||||
<div>
|
<div>
|
||||||
|
@ -32,11 +32,13 @@ function createMapStateToProps() {
|
|||||||
createMovieQualityProfileSelector(),
|
createMovieQualityProfileSelector(),
|
||||||
selectShowSearchAction(),
|
selectShowSearchAction(),
|
||||||
createExecutingCommandsSelector(),
|
createExecutingCommandsSelector(),
|
||||||
|
(state) => state.queue.details.items,
|
||||||
(
|
(
|
||||||
movie,
|
movie,
|
||||||
qualityProfile,
|
qualityProfile,
|
||||||
showSearchAction,
|
showSearchAction,
|
||||||
executingCommands
|
executingCommands,
|
||||||
|
queueItems
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
// If a movie is deleted this selector may fire before the parent
|
// If a movie is deleted this selector may fire before the parent
|
||||||
@ -62,12 +64,25 @@ function createMapStateToProps() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let queueStatus = null;
|
||||||
|
let queueState = null;
|
||||||
|
|
||||||
|
for (const q in queueItems) {
|
||||||
|
if (queueItems[q].movieId === movie.id) {
|
||||||
|
queueStatus = queueItems[q].status;
|
||||||
|
queueState = queueItems[q].trackedDownloadState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...movie,
|
...movie,
|
||||||
qualityProfile,
|
qualityProfile,
|
||||||
showSearchAction,
|
showSearchAction,
|
||||||
isRefreshingMovie,
|
isRefreshingMovie,
|
||||||
isSearchingMovie
|
isSearchingMovie,
|
||||||
|
queueStatus,
|
||||||
|
queueState
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -97,3 +97,8 @@ $hoverScale: 1.05;
|
|||||||
.externalLinks {
|
.externalLinks {
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
padding-left: 2px;
|
||||||
|
border-left: 4px solid $queueColor;
|
||||||
|
}
|
||||||
|
@ -113,6 +113,8 @@ class MovieIndexOverview extends Component {
|
|||||||
isMovieEditorActive,
|
isMovieEditorActive,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelectedChange,
|
onSelectedChange,
|
||||||
|
queueStatus,
|
||||||
|
queueState,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -170,6 +172,8 @@ class MovieIndexOverview extends Component {
|
|||||||
status={status}
|
status={status}
|
||||||
posterWidth={posterWidth}
|
posterWidth={posterWidth}
|
||||||
detailedProgressBar={overviewOptions.detailedProgressBar}
|
detailedProgressBar={overviewOptions.detailedProgressBar}
|
||||||
|
queueStatus={queueStatus}
|
||||||
|
queueState={queueState}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -300,7 +304,9 @@ MovieIndexOverview.propTypes = {
|
|||||||
onSelectedChange: PropTypes.func.isRequired,
|
onSelectedChange: PropTypes.func.isRequired,
|
||||||
tmdbId: PropTypes.number.isRequired,
|
tmdbId: PropTypes.number.isRequired,
|
||||||
imdbId: PropTypes.string,
|
imdbId: PropTypes.string,
|
||||||
youTubeTrailerId: PropTypes.string
|
youTubeTrailerId: PropTypes.string,
|
||||||
|
queueStatus: PropTypes.string,
|
||||||
|
queueState: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MovieIndexOverview;
|
export default MovieIndexOverview;
|
||||||
|
@ -108,6 +108,8 @@ class MovieIndexPoster extends Component {
|
|||||||
isMovieEditorActive,
|
isMovieEditorActive,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelectedChange,
|
onSelectedChange,
|
||||||
|
queueStatus,
|
||||||
|
queueState,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -224,6 +226,8 @@ class MovieIndexPoster extends Component {
|
|||||||
status={status}
|
status={status}
|
||||||
posterWidth={posterWidth}
|
posterWidth={posterWidth}
|
||||||
detailedProgressBar={detailedProgressBar}
|
detailedProgressBar={detailedProgressBar}
|
||||||
|
queueStatus={queueStatus}
|
||||||
|
queueState={queueState}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -301,7 +305,9 @@ MovieIndexPoster.propTypes = {
|
|||||||
onSelectedChange: PropTypes.func.isRequired,
|
onSelectedChange: PropTypes.func.isRequired,
|
||||||
tmdbId: PropTypes.number.isRequired,
|
tmdbId: PropTypes.number.isRequired,
|
||||||
imdbId: PropTypes.string,
|
imdbId: PropTypes.string,
|
||||||
youTubeTrailerId: PropTypes.string
|
youTubeTrailerId: PropTypes.string,
|
||||||
|
queueStatus: PropTypes.string,
|
||||||
|
queueState: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
MovieIndexPoster.defaultProps = {
|
MovieIndexPoster.defaultProps = {
|
||||||
|
@ -3,6 +3,9 @@ import React from 'react';
|
|||||||
import ProgressBar from 'Components/ProgressBar';
|
import ProgressBar from 'Components/ProgressBar';
|
||||||
import { sizes } from 'Helpers/Props';
|
import { sizes } from 'Helpers/Props';
|
||||||
import getProgressBarKind from 'Utilities/Movie/getProgressBarKind';
|
import getProgressBarKind from 'Utilities/Movie/getProgressBarKind';
|
||||||
|
import getQueueStatusText from 'Utilities/Movie/getQueueStatusText';
|
||||||
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './MovieIndexProgressBar.css';
|
import styles from './MovieIndexProgressBar.css';
|
||||||
|
|
||||||
function MovieIndexProgressBar(props) {
|
function MovieIndexProgressBar(props) {
|
||||||
@ -11,20 +14,43 @@ function MovieIndexProgressBar(props) {
|
|||||||
status,
|
status,
|
||||||
hasFile,
|
hasFile,
|
||||||
posterWidth,
|
posterWidth,
|
||||||
detailedProgressBar
|
detailedProgressBar,
|
||||||
|
queueStatus,
|
||||||
|
queueState
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const progress = 100;
|
const progress = 100;
|
||||||
|
const queueStatusText = getQueueStatusText(queueStatus, queueState);
|
||||||
|
let movieStatus = (status === 'released' && hasFile) ? 'downloaded' : status;
|
||||||
|
|
||||||
|
if (movieStatus === 'deleted') {
|
||||||
|
movieStatus = 'announced';
|
||||||
|
|
||||||
|
if (hasFile) {
|
||||||
|
movieStatus = 'downloaded';
|
||||||
|
} else {
|
||||||
|
movieStatus = 'released';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movieStatus === 'announced') {
|
||||||
|
movieStatus = translate('NotAvailable');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movieStatus === 'released') {
|
||||||
|
movieStatus = translate('Missing');
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
className={styles.progressBar}
|
className={styles.progressBar}
|
||||||
containerClassName={styles.progress}
|
containerClassName={styles.progress}
|
||||||
progress={progress}
|
progress={progress}
|
||||||
kind={getProgressBarKind(status, monitored, hasFile)}
|
kind={getProgressBarKind(status, monitored, hasFile, queueStatusText)}
|
||||||
size={detailedProgressBar ? sizes.MEDIUM : sizes.SMALL}
|
size={detailedProgressBar ? sizes.MEDIUM : sizes.SMALL}
|
||||||
showText={false} // Hide until we have multi version support
|
showText={detailedProgressBar}
|
||||||
width={posterWidth}
|
width={posterWidth}
|
||||||
|
text={(queueStatusText) ? queueStatusText.shortText : titleCase(movieStatus)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -34,7 +60,9 @@ MovieIndexProgressBar.propTypes = {
|
|||||||
hasFile: PropTypes.bool.isRequired,
|
hasFile: PropTypes.bool.isRequired,
|
||||||
status: PropTypes.string.isRequired,
|
status: PropTypes.string.isRequired,
|
||||||
posterWidth: PropTypes.number.isRequired,
|
posterWidth: PropTypes.number.isRequired,
|
||||||
detailedProgressBar: PropTypes.bool.isRequired
|
detailedProgressBar: PropTypes.bool.isRequired,
|
||||||
|
queueStatus: PropTypes.string,
|
||||||
|
queueState: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MovieIndexProgressBar;
|
export default MovieIndexProgressBar;
|
||||||
|
@ -98,6 +98,8 @@ class MovieIndexRow extends Component {
|
|||||||
onRefreshMoviePress,
|
onRefreshMoviePress,
|
||||||
onSearchPress,
|
onSearchPress,
|
||||||
onSelectedChange,
|
onSelectedChange,
|
||||||
|
queueStatus,
|
||||||
|
queueState,
|
||||||
movieRuntimeFormat
|
movieRuntimeFormat
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -315,6 +317,8 @@ class MovieIndexRow extends Component {
|
|||||||
>
|
>
|
||||||
<MovieFileStatusConnector
|
<MovieFileStatusConnector
|
||||||
movieId={id}
|
movieId={id}
|
||||||
|
queueStatus={queueStatus}
|
||||||
|
queueState={queueState}
|
||||||
/>
|
/>
|
||||||
</VirtualTableRowCell>
|
</VirtualTableRowCell>
|
||||||
);
|
);
|
||||||
@ -464,6 +468,8 @@ MovieIndexRow.propTypes = {
|
|||||||
tmdbId: PropTypes.number.isRequired,
|
tmdbId: PropTypes.number.isRequired,
|
||||||
imdbId: PropTypes.string,
|
imdbId: PropTypes.string,
|
||||||
youTubeTrailerId: PropTypes.string,
|
youTubeTrailerId: PropTypes.string,
|
||||||
|
queueStatus: PropTypes.string,
|
||||||
|
queueState: PropTypes.string,
|
||||||
movieRuntimeFormat: PropTypes.string.isRequired
|
movieRuntimeFormat: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import QueueDetails from 'Activity/Queue/QueueDetails';
|
|
||||||
import Icon from 'Components/Icon';
|
|
||||||
import Label from 'Components/Label';
|
import Label from 'Components/Label';
|
||||||
import ProgressBar from 'Components/ProgressBar';
|
import { kinds } from 'Helpers/Props';
|
||||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
|
||||||
import MovieQuality from 'Movie/MovieQuality';
|
import MovieQuality from 'Movie/MovieQuality';
|
||||||
|
import getQueueStatusText from 'Utilities/Movie/getQueueStatusText';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './MovieFileStatus.css';
|
import styles from './MovieFileStatus.css';
|
||||||
|
|
||||||
@ -13,47 +11,25 @@ function MovieFileStatus(props) {
|
|||||||
const {
|
const {
|
||||||
isAvailable,
|
isAvailable,
|
||||||
monitored,
|
monitored,
|
||||||
grabbed,
|
movieFile,
|
||||||
queueItem,
|
queueStatus,
|
||||||
movieFile
|
queueState
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const hasMovieFile = !!movieFile;
|
const hasMovieFile = !!movieFile;
|
||||||
const isQueued = !!queueItem;
|
|
||||||
const hasReleased = isAvailable;
|
const hasReleased = isAvailable;
|
||||||
|
|
||||||
if (isQueued) {
|
if (queueStatus) {
|
||||||
const {
|
const queueStatusText = getQueueStatusText(queueStatus, queueState);
|
||||||
sizeleft,
|
|
||||||
size
|
|
||||||
} = queueItem;
|
|
||||||
|
|
||||||
const progress = (100 - sizeleft / size * 100);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.center}>
|
<div className={styles.center}>
|
||||||
<QueueDetails
|
<Label
|
||||||
{...queueItem}
|
title={queueStatusText.longText}
|
||||||
progressBar={
|
kind={kinds.QUEUE}
|
||||||
<ProgressBar
|
>
|
||||||
title={translate('MovieIsDownloadingInterp', [progress.toFixed(1), queueItem.title])}
|
{queueStatusText.shortText}
|
||||||
progress={progress}
|
</Label>
|
||||||
kind={kinds.PURPLE}
|
|
||||||
size={sizes.MEDIUM}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabbed) {
|
|
||||||
return (
|
|
||||||
<div className={styles.center}>
|
|
||||||
<Icon
|
|
||||||
name={icons.DOWNLOADING}
|
|
||||||
title={translate('MovieIsDownloading')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -115,9 +91,9 @@ function MovieFileStatus(props) {
|
|||||||
MovieFileStatus.propTypes = {
|
MovieFileStatus.propTypes = {
|
||||||
isAvailable: PropTypes.bool,
|
isAvailable: PropTypes.bool,
|
||||||
monitored: PropTypes.bool.isRequired,
|
monitored: PropTypes.bool.isRequired,
|
||||||
grabbed: PropTypes.bool,
|
movieFile: PropTypes.object,
|
||||||
queueItem: PropTypes.object,
|
queueStatus: PropTypes.string,
|
||||||
movieFile: PropTypes.object
|
queueState: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MovieFileStatus;
|
export default MovieFileStatus;
|
||||||
|
@ -4,14 +4,12 @@ import React, { Component } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import createMovieSelector from 'Store/Selectors/createMovieSelector';
|
import createMovieSelector from 'Store/Selectors/createMovieSelector';
|
||||||
import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector';
|
|
||||||
import MovieFileStatus from './MovieFileStatus';
|
import MovieFileStatus from './MovieFileStatus';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
return createSelector(
|
return createSelector(
|
||||||
createMovieSelector(),
|
createMovieSelector(),
|
||||||
createQueueItemSelector(),
|
(movie) => {
|
||||||
(movie, queueItem) => {
|
|
||||||
const result = _.pick(movie, [
|
const result = _.pick(movie, [
|
||||||
'inCinemas',
|
'inCinemas',
|
||||||
'isAvailable',
|
'isAvailable',
|
||||||
@ -19,7 +17,6 @@ function createMapStateToProps() {
|
|||||||
'grabbed'
|
'grabbed'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
result.queueItem = queueItem;
|
|
||||||
result.movieFile = movie.movieFile;
|
result.movieFile = movie.movieFile;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -45,7 +42,9 @@ class MovieFileStatusConnector extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MovieFileStatusConnector.propTypes = {
|
MovieFileStatusConnector.propTypes = {
|
||||||
movieId: PropTypes.number.isRequired
|
movieId: PropTypes.number.isRequired,
|
||||||
|
queueStatus: PropTypes.string,
|
||||||
|
queueState: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(MovieFileStatusConnector);
|
export default connect(createMapStateToProps, mapDispatchToProps)(MovieFileStatusConnector);
|
||||||
|
@ -231,12 +231,7 @@ export const actionHandlers = handleThunks({
|
|||||||
params = getState().queue.details.params;
|
params = getState().queue.details.params;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure there are params before trying to fetch the queue
|
fetchQueueDetailsHelper(getState, params, dispatch);
|
||||||
// so we don't make a bad request to the server.
|
|
||||||
|
|
||||||
if (params && !_.isEmpty(params)) {
|
|
||||||
fetchQueueDetailsHelper(getState, params, dispatch);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
...createServerSideCollectionHandlers(
|
...createServerSideCollectionHandlers(
|
||||||
|
@ -14,6 +14,7 @@ module.exports = {
|
|||||||
dangerColor: '#f05050',
|
dangerColor: '#f05050',
|
||||||
warningColor: '#ffa500',
|
warningColor: '#ffa500',
|
||||||
infoColor: '#5d9cec',
|
infoColor: '#5d9cec',
|
||||||
|
queueColor: '#7a43b6',
|
||||||
purple: '#7a43b6',
|
purple: '#7a43b6',
|
||||||
pink: '#ff69b4',
|
pink: '#ff69b4',
|
||||||
radarrYellow,
|
radarrYellow,
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { kinds } from 'Helpers/Props';
|
import { kinds } from 'Helpers/Props';
|
||||||
|
|
||||||
function getProgressBarKind(status, monitored, hasFile) {
|
function getProgressBarKind(status, monitored, hasFile, queue = false) {
|
||||||
|
if (queue) {
|
||||||
|
return kinds.QUEUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (status === 'announced') {
|
if (status === 'announced') {
|
||||||
return kinds.PRIMARY;
|
return kinds.PRIMARY;
|
||||||
}
|
}
|
||||||
|
61
frontend/src/Utilities/Movie/getQueueStatusText.js
Normal file
61
frontend/src/Utilities/Movie/getQueueStatusText.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
|
export default function getQueueStatusText(queueStatus, queueState) {
|
||||||
|
if (!queueStatus) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let statusLong = translate('Downloading');
|
||||||
|
let statusShort = translate('Downloading');
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case queueStatus !== 'completed':
|
||||||
|
switch (queueStatus) {
|
||||||
|
case 'queue':
|
||||||
|
case 'paused':
|
||||||
|
case 'failed':
|
||||||
|
statusLong = `${translate('Downloading')}: ${translate(titleCase(queueStatus))}`;
|
||||||
|
statusShort = titleCase(queueStatus);
|
||||||
|
break;
|
||||||
|
case 'delay':
|
||||||
|
statusLong = `${translate('Downloading')}: ${translate('Pending')}`;
|
||||||
|
statusShort = translate('Pending');
|
||||||
|
break;
|
||||||
|
case 'DownloadClientUnavailable':
|
||||||
|
case 'warning':
|
||||||
|
statusLong = `${translate('Downloading')}: ${translate('Error')}`;
|
||||||
|
statusShort = translate('Error');
|
||||||
|
break;
|
||||||
|
case 'downloading':
|
||||||
|
statusLong = titleCase(queueStatus);
|
||||||
|
statusShort = titleCase(queueStatus);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case queueStatus === 'completed':
|
||||||
|
switch (queueState) {
|
||||||
|
case 'importPending':
|
||||||
|
statusLong = `${translate('Downloaded')}: ${translate('Pending')}`;
|
||||||
|
statusShort = translate('Downloaded');
|
||||||
|
break;
|
||||||
|
case 'importing':
|
||||||
|
statusLong = `${translate('Downloaded')}: ${translate('Importing')}`;
|
||||||
|
statusShort = translate('Downloaded');
|
||||||
|
break;
|
||||||
|
case 'failedPending':
|
||||||
|
statusLong = `${translate('Downloaded')}: ${translate('Waiting')}`;
|
||||||
|
statusShort = translate('Downloaded');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = { longText: statusLong, shortText: statusShort };
|
||||||
|
return result;
|
||||||
|
}
|
@ -762,6 +762,7 @@
|
|||||||
"UnableToLoadUISettings": "Unable to load UI settings",
|
"UnableToLoadUISettings": "Unable to load UI settings",
|
||||||
"Unavailable": "Unavailable",
|
"Unavailable": "Unavailable",
|
||||||
"Ungroup": "Ungroup",
|
"Ungroup": "Ungroup",
|
||||||
|
"Unreleased": "Unreleased",
|
||||||
"UnmappedFolders": "Unmapped Folders",
|
"UnmappedFolders": "Unmapped Folders",
|
||||||
"Unmonitored": "Unmonitored",
|
"Unmonitored": "Unmonitored",
|
||||||
"UnmonitoredHelpText": "Include unmonitored movies in the iCal feed",
|
"UnmonitoredHelpText": "Include unmonitored movies in the iCal feed",
|
||||||
|
Loading…
Reference in New Issue
Block a user