diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js
index 470dd0d3e..e1d630260 100644
--- a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js
+++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js
@@ -81,7 +81,8 @@ class AddNewMovie extends Component {
const {
error,
items,
- hasExistingMovies
+ hasExistingMovies,
+ colorImpairedMode
} = this.props;
const term = this.state.term;
@@ -141,6 +142,7 @@ class AddNewMovie extends Component {
return (
);
@@ -213,7 +215,8 @@ AddNewMovie.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
hasExistingMovies: PropTypes.bool.isRequired,
onMovieLookupChange: PropTypes.func.isRequired,
- onClearMovieLookup: PropTypes.func.isRequired
+ onClearMovieLookup: PropTypes.func.isRequired,
+ colorImpairedMode: PropTypes.bool.isRequired
};
export default AddNewMovie;
diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js
index 252d30058..b8d0e0c3e 100644
--- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js
+++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js
@@ -3,8 +3,10 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions';
+import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
+import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import parseUrl from 'Utilities/String/parseUrl';
import AddNewMovie from './AddNewMovie';
@@ -13,13 +15,15 @@ function createMapStateToProps() {
(state) => state.addMovie,
(state) => state.movies.items.length,
(state) => state.router.location,
- (addMovie, existingMoviesCount, location) => {
+ createUISettingsSelector(),
+ (addMovie, existingMoviesCount, location, uiSettings) => {
const { params } = parseUrl(location.search);
return {
...addMovie,
term: params.term,
- hasExistingMovies: existingMoviesCount > 0
+ hasExistingMovies: existingMoviesCount > 0,
+ colorImpairedMode: uiSettings.enableColorImpairedMode
};
}
);
@@ -29,7 +33,9 @@ const mapDispatchToProps = {
lookupMovie,
clearAddMovie,
fetchRootFolders,
- fetchImportExclusions
+ fetchImportExclusions,
+ fetchQueueDetails,
+ clearQueueDetails
};
class AddNewMovieConnector extends Component {
@@ -46,6 +52,7 @@ class AddNewMovieConnector extends Component {
componentDidMount() {
this.props.fetchRootFolders();
this.props.fetchImportExclusions();
+ this.props.fetchQueueDetails();
}
componentWillUnmount() {
@@ -54,6 +61,7 @@ class AddNewMovieConnector extends Component {
}
this.props.clearAddMovie();
+ this.props.clearQueueDetails();
}
//
@@ -102,7 +110,9 @@ AddNewMovieConnector.propTypes = {
lookupMovie: PropTypes.func.isRequired,
clearAddMovie: PropTypes.func.isRequired,
fetchRootFolders: PropTypes.func.isRequired,
- fetchImportExclusions: PropTypes.func.isRequired
+ fetchImportExclusions: PropTypes.func.isRequired,
+ fetchQueueDetails: PropTypes.func.isRequired,
+ clearQueueDetails: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector);
diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css
index ffa89f5e6..a631f7dcf 100644
--- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css
+++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css
@@ -27,9 +27,11 @@
}
.poster {
- flex: 0 0 170px;
+ position: relative;
+ display: block;
margin-right: 20px;
height: 250px;
+ background-color: $defaultColor;
}
.content {
@@ -86,6 +88,15 @@
pointer-events: all;
}
+.posterContainer {
+ position: relative;
+}
+
+.statusContainer {
+ margin-right: 22px;
+ font-weight: bold;
+}
+
@media only screen and (max-width: $breakpointMedium) {
.titleRow {
justify-content: space-between;
diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js
index 44692a785..e6d8e3b11 100644
--- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js
+++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js
@@ -7,6 +7,8 @@ import Link from 'Components/Link/Link';
import Tooltip from 'Components/Tooltip/Tooltip';
import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
+import MovieStatusLabel from 'Movie/Details/MovieStatusLabel';
+import MovieIndexProgressBar from 'Movie/Index/ProgressBar/MovieIndexProgressBar';
import MoviePoster from 'Movie/MoviePoster';
import translate from 'Utilities/String/translate';
import AddNewMovieModal from './AddNewMovieModal';
@@ -65,7 +67,14 @@ class AddNewMovieSearchResult extends Component {
images,
isExistingMovie,
isExclusionMovie,
- isSmallScreen
+ isSmallScreen,
+ colorImpairedMode,
+ id,
+ monitored,
+ hasFile,
+ isAvailable,
+ queueStatus,
+ queueState
} = this.props;
const {
@@ -85,12 +94,30 @@ class AddNewMovieSearchResult extends Component {
{
isSmallScreen ?
null :
-
+
+
+
+
+
+ {
+ isExistingMovie &&
+
+ }
+
}
@@ -176,13 +203,15 @@ class AddNewMovieSearchResult extends Component {
/>
{
- status === 'ended' &&
-
+ isExistingMovie && isSmallScreen &&
+
}
@@ -222,7 +251,15 @@ AddNewMovieSearchResult.propTypes = {
images: PropTypes.arrayOf(PropTypes.object).isRequired,
isExistingMovie: PropTypes.bool.isRequired,
isExclusionMovie: PropTypes.bool.isRequired,
- isSmallScreen: PropTypes.bool.isRequired
+ isSmallScreen: PropTypes.bool.isRequired,
+ id: PropTypes.number,
+ queueItems: PropTypes.arrayOf(PropTypes.object),
+ monitored: PropTypes.bool.isRequired,
+ hasFile: PropTypes.bool.isRequired,
+ isAvailable: PropTypes.bool.isRequired,
+ colorImpairedMode: PropTypes.bool,
+ queueStatus: PropTypes.string,
+ queueState: PropTypes.string
};
export default AddNewMovieSearchResult;
diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js
index fb843d67f..859abb57a 100644
--- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js
+++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js
@@ -10,11 +10,17 @@ function createMapStateToProps() {
createExistingMovieSelector(),
createExclusionMovieSelector(),
createDimensionsSelector(),
- (isExistingMovie, isExclusionMovie, dimensions) => {
+ (state) => state.queue.details.items,
+ (state) => state.tmdbId,
+ (isExistingMovie, isExclusionMovie, dimensions, queueItems, tmdbId) => {
+ const firstQueueItem = queueItems.find((q) => q.tmdbId === tmdbId);
+
return {
isExistingMovie,
isExclusionMovie,
- isSmallScreen: dimensions.isSmallScreen
+ isSmallScreen: dimensions.isSmallScreen,
+ queueStatus: firstQueueItem ? firstQueueItem.status : null,
+ queueState: firstQueueItem ? firstQueueItem.trackedDownloadState : null
};
}
);
diff --git a/frontend/src/Components/Label.css b/frontend/src/Components/Label.css
index b54bba63b..72cba7dd5 100644
--- a/frontend/src/Components/Label.css
+++ b/frontend/src/Components/Label.css
@@ -19,6 +19,10 @@
&.outline {
color: $dangerColor;
}
+
+ &:global(.colorImpaired) {
+ background: repeating-linear-gradient(90deg, color($dangerColor shade(5%)), color($dangerColor shade(5%)) 5px, color($dangerColor shade(15%)) 5px, color($dangerColor shade(15%)) 10px);
+ }
}
.default {
@@ -85,6 +89,10 @@
&.outline {
color: $warningColor;
}
+
+ &:global(.colorImpaired) {
+ background: repeating-linear-gradient(45deg, $warningColor, $warningColor 5px, color($warningColor tint(15%)) 5px, color($warningColor tint(15%)) 10px);
+ }
}
.queue {
diff --git a/frontend/src/Components/Label.js b/frontend/src/Components/Label.js
index 6f662ec7d..26fdf2074 100644
--- a/frontend/src/Components/Label.js
+++ b/frontend/src/Components/Label.js
@@ -11,6 +11,7 @@ function Label(props) {
size,
outline,
children,
+ colorImpairedMode,
...otherProps
} = props;
@@ -20,7 +21,8 @@ function Label(props) {
className,
styles[kind],
styles[size],
- outline && styles.outline
+ outline && styles.outline,
+ colorImpairedMode && 'colorImpaired'
)}
{...otherProps}
>
@@ -34,14 +36,16 @@ Label.propTypes = {
kind: PropTypes.oneOf(kinds.all).isRequired,
size: PropTypes.oneOf(sizes.all).isRequired,
outline: PropTypes.bool.isRequired,
- children: PropTypes.node.isRequired
+ children: PropTypes.node.isRequired,
+ colorImpairedMode: PropTypes.bool
};
Label.defaultProps = {
className: styles.label,
kind: kinds.DEFAULT,
size: sizes.SMALL,
- outline: false
+ outline: false,
+ colorImpairedMode: false
};
export default Label;
diff --git a/frontend/src/Movie/Details/MovieDetails.js b/frontend/src/Movie/Details/MovieDetails.js
index 6f2bbe789..5ccb3b520 100644
--- a/frontend/src/Movie/Details/MovieDetails.js
+++ b/frontend/src/Movie/Details/MovieDetails.js
@@ -286,7 +286,7 @@ class MovieDetails extends Component {
onMonitorTogglePress,
onRefreshPress,
onSearchPress,
- queueDetails,
+ queueItems,
movieRuntimeFormat
} = this.props;
@@ -523,7 +523,7 @@ class MovieDetails extends Component {
hasMovieFiles={hasMovieFiles}
monitored={monitored}
isAvailable={isAvailable}
- queueDetails={queueDetails}
+ queueItem={(queueItems.length > 0) ? queueItems[0] : null}
/>
@@ -794,7 +794,7 @@ MovieDetails.propTypes = {
onRefreshPress: PropTypes.func.isRequired,
onSearchPress: PropTypes.func.isRequired,
onGoToMovie: PropTypes.func.isRequired,
- queueDetails: PropTypes.object,
+ queueItems: PropTypes.arrayOf(PropTypes.object),
movieRuntimeFormat: PropTypes.string.isRequired
};
diff --git a/frontend/src/Movie/Details/MovieDetailsConnector.js b/frontend/src/Movie/Details/MovieDetailsConnector.js
index 2ab6b9167..f2c51788b 100644
--- a/frontend/src/Movie/Details/MovieDetailsConnector.js
+++ b/frontend/src/Movie/Details/MovieDetailsConnector.js
@@ -89,10 +89,10 @@ function createMapStateToProps() {
createAllMoviesSelector(),
createCommandsSelector(),
createDimensionsSelector(),
- (state) => state.queue.details,
+ (state) => state.queue.details.items,
(state) => state.app.isSidebarVisible,
(state) => state.settings.ui.item.movieRuntimeFormat,
- (titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, queueDetails, isSidebarVisible, movieRuntimeFormat) => {
+ (titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, queueItems, isSidebarVisible, movieRuntimeFormat) => {
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
const movie = sortedMovies[movieIndex];
@@ -165,7 +165,7 @@ function createMapStateToProps() {
nextMovie,
isSmallScreen: dimensions.isSmallScreen,
isSidebarVisible,
- queueDetails,
+ queueItems,
movieRuntimeFormat
};
}
diff --git a/frontend/src/Movie/Details/MovieStatusLabel.css b/frontend/src/Movie/Details/MovieStatusLabel.css
index fff54bd98..9a315858f 100644
--- a/frontend/src/Movie/Details/MovieStatusLabel.css
+++ b/frontend/src/Movie/Details/MovieStatusLabel.css
@@ -1,24 +1,29 @@
-.missing {
- padding-left: 2px;
- border-left: 4px solid $dangerColor;
-}
-
-.downloaded {
- padding-left: 2px;
- border-left: 4px solid $successColor;
-}
-
-.notAvailable {
- padding-left: 2px;
- border-left: 4px solid $primaryColor;
-}
-
-.unmonitored {
- padding-left: 2px;
- border-left: 4px solid $warningColor;
-}
-
.queue {
padding-left: 2px;
border-left: 4px solid $queueColor;
}
+
+.continuing {
+ padding-left: 2px;
+ border-left: 4px solid $primaryColor;
+}
+
+.availNotMonitored {
+ padding-left: 2px;
+ border-left: 4px solid $darkGray;
+}
+
+.ended {
+ padding-left: 2px;
+ border-left: 4px solid $successColor;
+}
+
+.missingMonitored {
+ padding-left: 2px;
+ border-left: 4px solid $dangerColor;
+}
+
+.missingUnmonitored {
+ padding-left: 2px;
+ border-left: 4px solid $warningColor;
+}
diff --git a/frontend/src/Movie/Details/MovieStatusLabel.js b/frontend/src/Movie/Details/MovieStatusLabel.js
index c605bb91d..c1b3a7a98 100644
--- a/frontend/src/Movie/Details/MovieStatusLabel.js
+++ b/frontend/src/Movie/Details/MovieStatusLabel.js
@@ -1,15 +1,17 @@
import PropTypes from 'prop-types';
import React from 'react';
+import Label from 'Components/Label';
+import { kinds, sizes } from 'Helpers/Props';
import getQueueStatusText from 'Utilities/Movie/getQueueStatusText';
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
import translate from 'Utilities/String/translate';
import styles from './MovieStatusLabel.css';
-function getMovieStatus(hasFile, isMonitored, isAvailable, queueDetails = false) {
+function getMovieStatus(hasFile, isMonitored, isAvailable, queueItem = false) {
- if (queueDetails.items[0]) {
- const queueStatus = queueDetails.items[0].status;
- const queueState = queueDetails.items[0].trackedDownloadStatus;
+ if (queueItem) {
+ const queueStatus = queueItem.status;
+ const queueState = queueItem.trackedDownloadStatus;
const queueStatusText = getQueueStatusText(queueStatus, queueState);
if (queueStatusText) {
@@ -17,19 +19,23 @@ function getMovieStatus(hasFile, isMonitored, isAvailable, queueDetails = false)
}
}
- if (hasFile) {
- return 'downloaded';
+ if (hasFile && !isMonitored) {
+ return 'availNotMonitored';
}
- if (!isMonitored) {
- return 'unmonitored';
+ if (hasFile) {
+ return 'ended';
+ }
+
+ if (isAvailable && !isMonitored && !hasFile) {
+ return 'missingUnmonitored';
}
if (isAvailable && !hasFile) {
- return 'missing';
+ return 'missingMonitored';
}
- return 'notAvailable';
+ return 'continuing';
}
function MovieStatusLabel(props) {
@@ -37,16 +43,61 @@ function MovieStatusLabel(props) {
hasMovieFiles,
monitored,
isAvailable,
- queueDetails
+ queueItem,
+ useLabel,
+ colorImpairedMode
} = props;
- const status = getMovieStatus(hasMovieFiles, monitored, isAvailable, queueDetails);
+ let status = getMovieStatus(hasMovieFiles, monitored, isAvailable, queueItem);
let statusClass = status;
- if (queueDetails.items.length) {
+ if (status === 'availNotMonitored' || status === 'ended') {
+ status = 'downloaded';
+ }
+ if (status === 'missingMonitored' || status === 'missingUnmonitored') {
+ status = 'missing';
+ }
+ if (status === 'continuing') {
+ status = 'notAvailable';
+ }
+
+ if (queueItem) {
statusClass = 'queue';
}
+ if (useLabel) {
+ let kind = kinds.SUCCESS;
+
+ switch (statusClass) {
+ case 'queue':
+ kind = kinds.QUEUE;
+ break;
+ case 'missingMonitored':
+ kind = kinds.DANGER;
+ break;
+ case 'continuing':
+ kind = kinds.INFO;
+ break;
+ case 'availNotMonitored':
+ kind = kinds.DEFAULT;
+ break;
+ case 'missingUnmonitored':
+ kind = kinds.WARNING;
+ break;
+ default:
+ }
+
+ return (
+
+ );
+ }
+
return (