diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css
index 616aeaf3c..9bfb5a493 100644
--- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css
+++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css
@@ -31,3 +31,7 @@
margin: 0 10px 0 12px;
text-align: left;
}
+
+.importError {
+ margin-left: 10px;
+}
diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js
index f3c211a9a..d3b1eb1e8 100644
--- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js
+++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js
@@ -3,11 +3,13 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
// import CheckInput from 'Components/Form/CheckInput';
import FormInputGroup from 'Components/Form/FormInputGroup';
+import Icon from 'Components/Icon';
import Button from 'Components/Link/Button';
import SpinnerButton from 'Components/Link/SpinnerButton';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import PageContentFooter from 'Components/Page/PageContentFooter';
-import { inputTypes, kinds } from 'Helpers/Props';
+import Popover from 'Components/Tooltip/Popover';
+import { icons, inputTypes, kinds, tooltipPositions } from 'Helpers/Props';
import styles from './ImportMovieFooter.css';
const MIXED = 'mixed';
@@ -93,7 +95,10 @@ class ImportMovieFooter extends Component {
isMonitorMixed,
isQualityProfileIdMixed,
isMinimumAvailabilityMixed,
+ hasUnsearchedItems,
+ importError,
onImportPress,
+ onLookupPress,
onCancelLookupPress
} = this.props;
@@ -167,27 +172,71 @@ class ImportMovieFooter extends Component {
{
- isLookingUpMovie &&
+ isLookingUpMovie ?
+ :
+ null
}
{
- isLookingUpMovie &&
+ hasUnsearchedItems ?
+ :
+ null
+ }
+
+ {
+ isLookingUpMovie ?
+ /> :
+ null
+ }
+
+ {
+ isLookingUpMovie ?
+ 'Processing Folders' :
+ null
}
{
- isLookingUpMovie &&
- 'Processing Folders'
+ importError ?
+
+ }
+ title="Import Errors"
+ body={
+
+ {
+ importError.responseJSON.map((error, index) => {
+ return (
+ -
+ {error.errorMessage}
+
+ );
+ })
+ }
+
+ }
+ position={tooltipPositions.RIGHT}
+ /> :
+ null
}
@@ -206,8 +255,11 @@ ImportMovieFooter.propTypes = {
isMonitorMixed: PropTypes.bool.isRequired,
isQualityProfileIdMixed: PropTypes.bool.isRequired,
isMinimumAvailabilityMixed: PropTypes.bool.isRequired,
+ hasUnsearchedItems: PropTypes.bool.isRequired,
+ importError: PropTypes.object,
onInputChange: PropTypes.func.isRequired,
onImportPress: PropTypes.func.isRequired,
+ onLookupPress: PropTypes.func.isRequired,
onCancelLookupPress: PropTypes.func.isRequired
};
diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js
index 3c0c58325..f43cfa8e4 100644
--- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js
+++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js
@@ -1,7 +1,7 @@
import _ from 'lodash';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
-import { cancelLookupMovie } from 'Store/Actions/importMovieActions';
+import { cancelLookupMovie, lookupUnsearchedMovies } from 'Store/Actions/importMovieActions';
import ImportMovieFooter from './ImportMovieFooter';
function isMixed(items, selectedIds, defaultValue, key) {
@@ -25,12 +25,14 @@ function createMapStateToProps() {
const {
isLookingUpMovie,
isImporting,
- items
+ items,
+ importError
} = importMovie;
const isMonitorMixed = isMixed(items, selectedIds, defaultMonitor, 'monitor');
const isQualityProfileIdMixed = isMixed(items, selectedIds, defaultQualityProfileId, 'qualityProfileId');
const isMinimumAvailabilityMixed = isMixed(items, selectedIds, defaultMinimumAvailability, 'minimumAvailability');
+ const hasUnsearchedItems = !isLookingUpMovie && items.some((item) => !item.isPopulated);
return {
selectedCount: selectedIds.length,
@@ -41,13 +43,16 @@ function createMapStateToProps() {
defaultMinimumAvailability,
isMonitorMixed,
isQualityProfileIdMixed,
- isMinimumAvailabilityMixed
+ isMinimumAvailabilityMixed,
+ importError,
+ hasUnsearchedItems
};
}
);
}
const mapDispatchToProps = {
+ onLookupPress: lookupUnsearchedMovies,
onCancelLookupPress: cancelLookupMovie
};
diff --git a/frontend/src/Store/Actions/importMovieActions.js b/frontend/src/Store/Actions/importMovieActions.js
index 20d172f6d..a3aa59a86 100644
--- a/frontend/src/Store/Actions/importMovieActions.js
+++ b/frontend/src/Store/Actions/importMovieActions.js
@@ -35,6 +35,7 @@ export const defaultState = {
export const QUEUE_LOOKUP_MOVIE = 'importMovie/queueLookupMovie';
export const START_LOOKUP_MOVIE = 'importMovie/startLookupMovie';
export const CANCEL_LOOKUP_MOVIE = 'importMovie/cancelLookupMovie';
+export const LOOKUP_UNSEARCHED_MOVIES = 'importMovie/lookupUnsearchedMovies';
export const CLEAR_IMPORT_MOVIE = 'importMovie/clearImportMovie';
export const SET_IMPORT_MOVIE_VALUE = 'importMovie/setImportMovieValue';
export const IMPORT_MOVIE = 'importMovie/importMovie';
@@ -45,6 +46,7 @@ export const IMPORT_MOVIE = 'importMovie/importMovie';
export const queueLookupMovie = createThunk(QUEUE_LOOKUP_MOVIE);
export const startLookupMovie = createThunk(START_LOOKUP_MOVIE);
export const importMovie = createThunk(IMPORT_MOVIE);
+export const lookupUnsearchedMovies = createThunk(LOOKUP_UNSEARCHED_MOVIES);
export const clearImportMovie = createAction(CLEAR_IMPORT_MOVIE);
export const cancelLookupMovie = createAction(CANCEL_LOOKUP_MOVIE);
@@ -179,6 +181,29 @@ export const actionHandlers = handleThunks({
});
},
+ [LOOKUP_UNSEARCHED_MOVIES]: function(getState, payload, dispatch) {
+ const state = getState().importMovie;
+
+ if (state.isLookingUpMovie) {
+ return;
+ }
+
+ state.items.forEach((item) => {
+ const id = item.id;
+
+ if (
+ !item.isPopulated &&
+ !queue.includes(id)
+ ) {
+ queue.push(item.id);
+ }
+ });
+
+ if (queue.length) {
+ dispatch(startLookupMovie({ start: true }));
+ }
+ },
+
[IMPORT_MOVIE]: function(getState, payload, dispatch) {
dispatch(set({ section, isImporting: true }));
@@ -215,7 +240,8 @@ export const actionHandlers = handleThunks({
set({
section,
isImporting: false,
- isImported: true
+ isImported: true,
+ importError: null
}),
...data.map((movie) => updateItem({ section: 'movies', ...movie })),
@@ -227,19 +253,19 @@ export const actionHandlers = handleThunks({
});
promise.fail((xhr) => {
- dispatch(batchActions(
+ dispatch(batchActions([
set({
section,
isImporting: false,
- isImported: true
+ isImported: true,
+ importError: xhr
}),
- addedIds.map((id) => updateItem({
+ ...addedIds.map((id) => updateItem({
section,
- id,
- importError: xhr
+ id
}))
- ));
+ ]));
});
}
});