diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js index 7ead3f98f..629993d2a 100644 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js +++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js @@ -46,8 +46,8 @@ const columns = [ isVisible: true }, { - name: 'language', - label: 'Language', + name: 'languages', + label: 'Languages', isSortable: true, isVisible: true }, diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js index 98a82f3ba..4259657f8 100644 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js +++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js @@ -109,7 +109,7 @@ class InteractiveImportModalContentConnector extends Component { const { movie, quality, - language + languages } = item; if (!movie) { @@ -122,7 +122,7 @@ class InteractiveImportModalContentConnector extends Component { return false; } - if (!language) { + if (!languages) { this.setState({ interactiveImportErrorMessage: 'Language must be chosen for each selected file' }); return false; } @@ -132,7 +132,7 @@ class InteractiveImportModalContentConnector extends Component { folderName: item.folderName, movieId: movie.id, quality, - languages: [language], + languages, downloadId: this.props.downloadId }); } diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js index 0bc39d616..29489b4c6 100644 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js +++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js @@ -36,13 +36,13 @@ class InteractiveImportRow extends Component { id, movie, quality, - language + languages } = this.props; if ( movie && quality && - language + languages ) { this.props.onSelectedChange({ id, value: true }); } @@ -53,7 +53,7 @@ class InteractiveImportRow extends Component { id, movie, quality, - language, + languages, isSelected, onValidRowChange } = this.props; @@ -61,7 +61,7 @@ class InteractiveImportRow extends Component { if ( prevProps.movie === movie && prevProps.quality === quality && - prevProps.language === language && + prevProps.languages === languages && prevProps.isSelected === isSelected ) { return; @@ -70,7 +70,7 @@ class InteractiveImportRow extends Component { const isValid = !!( movie && quality && - language + languages ); if (isSelected && !isValid) { @@ -134,7 +134,7 @@ class InteractiveImportRow extends Component { relativePath, movie, quality, - language, + languages, size, rejections, isSelected, @@ -151,9 +151,8 @@ class InteractiveImportRow extends Component { const showMoviePlaceholder = isSelected && !movie; const showQualityPlaceholder = isSelected && !quality; - const showLanguagePlaceholder = isSelected && !language; - // TODO - Placeholder till we implement selection of multiple languages - const languages = [language]; + const showLanguagePlaceholder = isSelected && !languages; + return ( l.id) : []} onModalClose={this.onSelectLanguageModalClose} /> @@ -284,7 +283,7 @@ InteractiveImportRow.propTypes = { relativePath: PropTypes.string.isRequired, movie: PropTypes.object, quality: PropTypes.object, - language: PropTypes.object, + languages: PropTypes.arrayOf(PropTypes.object), size: PropTypes.number.isRequired, rejections: PropTypes.arrayOf(PropTypes.object).isRequired, isSelected: PropTypes.bool, diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModal.js b/frontend/src/InteractiveImport/Language/SelectLanguageModal.js index 938d26a6d..01eb401ee 100644 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModal.js +++ b/frontend/src/InteractiveImport/Language/SelectLanguageModal.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import { sizes } from 'Helpers/Props'; import Modal from 'Components/Modal/Modal'; import SelectLanguageModalContentConnector from './SelectLanguageModalContentConnector'; @@ -19,6 +20,7 @@ class SelectLanguageModal extends Component { { - return { - key: language.id, - value: language.name +class SelectLanguageModalContent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + const { + languageIds + } = props; + + this.state = { + languageIds }; - }); - - return ( - - - Manual Import - Select Language - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
Unable to load languages
- } - - { - isPopulated && !error && -
- - Language - - - -
- } -
- - - - -
- ); + } + + // + // Listeners + + onLanguageChange = ({ value, name }) => { + const { + languageIds + } = this.state; + + const changedId = parseInt(name); + + let newLanguages = languageIds; + + if (value) { + newLanguages.push(changedId); + } + + if (!value) { + newLanguages = languageIds.filter((i) => i !== changedId); + } + + this.setState({ languageIds: newLanguages }); + } + + onLanguageSelect = () => { + this.props.onLanguageSelect(this.state); + } + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + items, + onModalClose + } = this.props; + + const { + languageIds + } = this.state; + + return ( + + + Manual Import - Select Language + + + + { + isFetching && + + } + + { + !isFetching && !!error && +
Unable to load languages
+ } + + { + isPopulated && !error && +
+ { + items.map(( language ) => { + return ( + + {language.name} + + + ); + }) + } +
+ } +
+ + + + + + +
+ ); + } } SelectLanguageModalContent.propTypes = { - languageId: PropTypes.number.isRequired, + languageIds: PropTypes.arrayOf(PropTypes.number).isRequired, isFetching: PropTypes.bool.isRequired, isPopulated: PropTypes.bool.isRequired, error: PropTypes.object, @@ -84,4 +143,8 @@ SelectLanguageModalContent.propTypes = { onModalClose: PropTypes.func.isRequired }; +SelectLanguageModalContent.defaultProps = { + languages: [] +}; + export default SelectLanguageModalContent; diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js b/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js index 846c6acc9..bef73d0e4 100644 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js +++ b/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js @@ -47,15 +47,19 @@ class SelectLanguageModalContentConnector extends Component { // // Listeners - onLanguageSelect = ({ value }) => { - const languageId = parseInt(value); + onLanguageSelect = ({ languageIds }) => { + const languages = []; - const language = _.find(this.props.items, - (item) => item.id === languageId); + languageIds.forEach((languageId) => { + const language = _.find(this.props.items, + (item) => item.id === parseInt(languageId)); + + languages.push(language); + }); this.props.dispatchUpdateInteractiveImportItems({ ids: this.props.ids, - language + languages }); this.props.onModalClose(true); diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorRow.js b/frontend/src/MovieFile/Editor/MovieFileEditorRow.js index 94f4ae36c..371419daa 100644 --- a/frontend/src/MovieFile/Editor/MovieFileEditorRow.js +++ b/frontend/src/MovieFile/Editor/MovieFileEditorRow.js @@ -219,7 +219,7 @@ class MovieFileEditorRow extends Component { l.id) : []} onModalClose={this.onSelectLanguageModalClose} /> diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js b/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js index e3b52f02b..c5da66d51 100644 --- a/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js +++ b/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js @@ -1,5 +1,4 @@ /* eslint max-params: 0 */ -import _ from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; @@ -71,28 +70,6 @@ class MovieFileEditorTableContentConnector extends Component { // // Render - // - // Listeners - - onLanguageChange = (movieFileIds, languageId) => { - const language = _.find(this.props.languages, { id: languageId }); - // TODO - Placeholder till we implement selection of multiple languages - const languages = [language]; - this.props.dispatchUpdateMovieFiles({ movieFileIds, languages }); - } - - onQualityChange = (movieFileIds, qualityId) => { - const quality = { - quality: _.find(this.props.qualities, { id: qualityId }), - revision: { - version: 1, - real: 0 - } - }; - - this.props.dispatchUpdateMovieFiles({ movieFileIds, quality }); - } - render() { const { dispatchFetchLanguages, @@ -104,8 +81,6 @@ class MovieFileEditorTableContentConnector extends Component { return ( ); } diff --git a/frontend/src/MovieFile/Language/SelectLanguageModalContent.js b/frontend/src/MovieFile/Language/SelectLanguageModalContent.js deleted file mode 100644 index 2f16d417b..000000000 --- a/frontend/src/MovieFile/Language/SelectLanguageModalContent.js +++ /dev/null @@ -1,87 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { inputTypes } from 'Helpers/Props'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalFooter from 'Components/Modal/ModalFooter'; - -function SelectLanguageModalContent(props) { - const { - languageId, - isFetching, - isPopulated, - error, - items, - onModalClose, - onLanguageSelect - } = props; - - const languageOptions = items.map(( language ) => { - return { - key: language.id, - value: language.name - }; - }); - - return ( - - - Manual Import - Select Language - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
Unable to load languages
- } - - { - isPopulated && !error && -
- - Language - - - -
- } -
- - - - -
- ); -} - -SelectLanguageModalContent.propTypes = { - languageId: PropTypes.number.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onLanguageSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectLanguageModalContent; diff --git a/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js b/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js index 6625bc57a..02792be02 100644 --- a/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js +++ b/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js @@ -5,7 +5,7 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { fetchLanguages } from 'Store/Actions/settingsActions'; import { updateMovieFiles } from 'Store/Actions/movieFileActions'; -import SelectLanguageModalContent from './SelectLanguageModalContent'; +import SelectLanguageModalContent from 'InteractiveImport/Language/SelectLanguageModalContent'; function createMapStateToProps() { return createSelector( @@ -47,15 +47,20 @@ class SelectLanguageModalContentConnector extends Component { // // Listeners - onLanguageSelect = ({ value }) => { - const languageId = parseInt(value); + onLanguageSelect = ({ languageIds }) => { + const languages = []; - const language = _.find(this.props.items, - (item) => item.id === languageId); - const languages = [language]; - const movieFileIds = this.props.ids; + languageIds.forEach((languageId) => { + const language = _.find(this.props.items, + (item) => item.id === parseInt(languageId)); - this.props.dispatchupdateMovieFiles({ movieFileIds, languages }); + languages.push(language); + }); + + this.props.dispatchupdateMovieFiles({ + movieFileIds: this.props.ids, + languages + }); this.props.onModalClose(true); } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs index c4763fe0a..f21813e60 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs @@ -177,7 +177,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual var localMovie = new LocalMovie(); localMovie.Path = file; localMovie.Quality = QualityParser.ParseQuality(file); - localMovie.Languages = LanguageParser.ParseLanguages(file); + localMovie.Languages = LanguageParser.EnhanceLanguages(file, LanguageParser.ParseLanguages(file)); localMovie.Size = _diskProvider.GetFileSize(file); return MapItem(new ImportDecision(localMovie, new Rejection("Unknown Movie")), rootFolder, downloadId, null);