New: Select Multiple Languages on Manual Import

pull/4026/head
Qstick 5 years ago
parent 4385acef99
commit 02c35f963e

@ -46,8 +46,8 @@ const columns = [
isVisible: true
},
{
name: 'language',
label: 'Language',
name: 'languages',
label: 'Languages',
isSortable: true,
isVisible: true
},

@ -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
});
}

@ -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 (
<TableRow>
<TableSelectCell
@ -209,7 +208,7 @@ class InteractiveImportRow extends Component {
}
{
!showLanguagePlaceholder && !!language &&
!showLanguagePlaceholder && !!languages &&
<MovieLanguage
className={styles.label}
languages={languages}
@ -269,7 +268,7 @@ class InteractiveImportRow extends Component {
<SelectLanguageModal
isOpen={isSelectLanguageModalOpen}
ids={[id]}
languageId={language ? language.id : 0}
languageIds={languages ? languages.map((l) => l.id) : []}
onModalClose={this.onSelectLanguageModalClose}
/>
</TableRow>
@ -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,

@ -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 {
<Modal
isOpen={isOpen}
onModalClose={onModalClose}
size={sizes.MEDIUM}
>
<SelectLanguageModalContentConnector
{...otherProps}

@ -0,0 +1,4 @@
.languageInput {
display: flex;
margin-bottom: 0;
}

@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
import { inputTypes } from 'Helpers/Props';
import React, { Component } from 'react';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
import Button from 'Components/Link/Button';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import Form from 'Components/Form/Form';
@ -11,71 +11,130 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalHeader from 'Components/Modal/ModalHeader';
import ModalBody from 'Components/Modal/ModalBody';
import ModalFooter from 'Components/Modal/ModalFooter';
import styles from './SelectLanguageModalContent.css';
function SelectLanguageModalContent(props) {
const {
languageId,
isFetching,
isPopulated,
error,
items,
onModalClose,
onLanguageSelect
} = props;
const languageOptions = items.map(( language ) => {
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 (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Manual Import - Select Language
</ModalHeader>
<ModalBody>
{
isFetching &&
<LoadingIndicator />
}
{
!isFetching && !!error &&
<div>Unable to load languages</div>
}
{
isPopulated && !error &&
<Form>
<FormGroup>
<FormLabel>Language</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="language"
value={languageId}
values={languageOptions}
onChange={onLanguageSelect}
/>
</FormGroup>
</Form>
}
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>
Cancel
</Button>
</ModalFooter>
</ModalContent>
);
}
//
// 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 (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Manual Import - Select Language
</ModalHeader>
<ModalBody>
{
isFetching &&
<LoadingIndicator />
}
{
!isFetching && !!error &&
<div>Unable to load languages</div>
}
{
isPopulated && !error &&
<Form>
{
items.map(( language ) => {
return (
<FormGroup
key={language.id}
size={sizes.EXTRA_SMALL}
className={styles.languageInput}
>
<FormLabel>{language.name}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name={language.id.toString()}
value={languageIds.includes(language.id)}
onChange={this.onLanguageChange}
/>
</FormGroup>
);
})
}
</Form>
}
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>
Cancel
</Button>
<Button
kind={kinds.SUCCESS}
onPress={this.onLanguageSelect}
>
Select Languges
</Button>
</ModalFooter>
</ModalContent>
);
}
}
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;

@ -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);

@ -219,7 +219,7 @@ class MovieFileEditorRow extends Component {
<SelectLanguageModal
isOpen={isSelectLanguageModalOpen}
ids={[id]}
languageId={languages[0] ? languages[0].id : 0}
languageIds={languages ? languages.map((l) => l.id) : []}
onModalClose={this.onSelectLanguageModalClose}
/>
</TableRow>

@ -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 (
<MovieFileEditorTableContent
{...otherProps}
onLanguageChange={this.onLanguageChange}
onQualityChange={this.onQualityChange}
/>
);
}

@ -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 (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Manual Import - Select Language
</ModalHeader>
<ModalBody>
{
isFetching &&
<LoadingIndicator />
}
{
!isFetching && !!error &&
<div>Unable to load languages</div>
}
{
isPopulated && !error &&
<Form>
<FormGroup>
<FormLabel>Language</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="language"
value={languageId}
values={languageOptions}
onChange={onLanguageSelect}
/>
</FormGroup>
</Form>
}
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>
Cancel
</Button>
</ModalFooter>
</ModalContent>
);
}
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;

@ -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);
}

@ -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);

Loading…
Cancel
Save