diff --git a/frontend/src/Components/Page/PageConnector.js b/frontend/src/Components/Page/PageConnector.js index 664a48d3c..a75370d12 100644 --- a/frontend/src/Components/Page/PageConnector.js +++ b/frontend/src/Components/Page/PageConnector.js @@ -8,7 +8,7 @@ import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions'; import { fetchCustomFilters } from 'Store/Actions/customFilterActions'; import { fetchMovies } from 'Store/Actions/movieActions'; import { fetchTags } from 'Store/Actions/tagActions'; -import { fetchQualityProfiles, fetchUISettings, fetchLanguages } from 'Store/Actions/settingsActions'; +import { fetchQualityProfiles, fetchUISettings, fetchLanguages, fetchNetImports } from 'Store/Actions/settingsActions'; import { fetchStatus } from 'Store/Actions/systemActions'; import ErrorPage from './ErrorPage'; import LoadingPage from './LoadingPage'; @@ -48,6 +48,7 @@ const selectIsPopulated = createSelector( (state) => state.settings.ui.isPopulated, (state) => state.settings.qualityProfiles.isPopulated, (state) => state.settings.languages.isPopulated, + (state) => state.settings.netImports.isPopulated, (state) => state.system.status.isPopulated, ( customFiltersIsPopulated, @@ -55,6 +56,7 @@ const selectIsPopulated = createSelector( uiSettingsIsPopulated, qualityProfilesIsPopulated, languagesIsPopulated, + netImportsIsPopulated, systemStatusIsPopulated ) => { return ( @@ -63,6 +65,7 @@ const selectIsPopulated = createSelector( uiSettingsIsPopulated && qualityProfilesIsPopulated && languagesIsPopulated && + netImportsIsPopulated && systemStatusIsPopulated ); } @@ -74,6 +77,7 @@ const selectErrors = createSelector( (state) => state.settings.ui.error, (state) => state.settings.qualityProfiles.error, (state) => state.settings.languages.error, + (state) => state.settings.netImports.error, (state) => state.system.status.error, ( customFiltersError, @@ -81,6 +85,7 @@ const selectErrors = createSelector( uiSettingsError, qualityProfilesError, languagesError, + netImportsError, systemStatusError ) => { const hasError = !!( @@ -89,6 +94,7 @@ const selectErrors = createSelector( uiSettingsError || qualityProfilesError || languagesError || + netImportsError || systemStatusError ); @@ -99,6 +105,7 @@ const selectErrors = createSelector( uiSettingsError, qualityProfilesError, languagesError, + netImportsError, systemStatusError }; } @@ -146,6 +153,9 @@ function createMapDispatchToProps(dispatch, props) { dispatchFetchLanguages() { dispatch(fetchLanguages()); }, + dispatchFetchNetImports() { + dispatch(fetchNetImports()); + }, dispatchFetchUISettings() { dispatch(fetchUISettings()); }, @@ -181,6 +191,7 @@ class PageConnector extends Component { this.props.dispatchFetchTags(); this.props.dispatchFetchQualityProfiles(); this.props.dispatchFetchLanguages(); + this.props.dispatchFetchNetImports(); this.props.dispatchFetchUISettings(); this.props.dispatchFetchStatus(); } @@ -204,6 +215,7 @@ class PageConnector extends Component { dispatchFetchTags, dispatchFetchQualityProfiles, dispatchFetchLanguages, + dispatchFetchNetImports, dispatchFetchUISettings, dispatchFetchStatus, ...otherProps @@ -242,6 +254,7 @@ PageConnector.propTypes = { dispatchFetchTags: PropTypes.func.isRequired, dispatchFetchQualityProfiles: PropTypes.func.isRequired, dispatchFetchLanguages: PropTypes.func.isRequired, + dispatchFetchNetImports: PropTypes.func.isRequired, dispatchFetchUISettings: PropTypes.func.isRequired, dispatchFetchStatus: PropTypes.func.isRequired, onSidebarVisibleChange: PropTypes.func.isRequired diff --git a/frontend/src/Movie/Details/Cast/MovieCastPostersConnector.js b/frontend/src/Movie/Details/Cast/MovieCastPostersConnector.js deleted file mode 100644 index 5311bedbe..000000000 --- a/frontend/src/Movie/Details/Cast/MovieCastPostersConnector.js +++ /dev/null @@ -1,25 +0,0 @@ -import _ from 'lodash'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import MovieCastPosters from './MovieCastPosters'; - -function createMapStateToProps() { - return createSelector( - (state) => state.moviePeople.items, - (people) => { - const cast = _.reduce(people, (acc, person) => { - if (person.type === 'cast') { - acc.push(person); - } - - return acc; - }, []); - - return { - cast - }; - } - ); -} - -export default connect(createMapStateToProps)(MovieCastPosters); diff --git a/frontend/src/Movie/Details/Cast/MovieCastPoster.js b/frontend/src/Movie/Details/Credits/Cast/MovieCastPoster.js similarity index 56% rename from frontend/src/Movie/Details/Cast/MovieCastPoster.js rename to frontend/src/Movie/Details/Credits/Cast/MovieCastPoster.js index 5237a72a4..d31da7e9b 100644 --- a/frontend/src/Movie/Details/Cast/MovieCastPoster.js +++ b/frontend/src/Movie/Details/Credits/Cast/MovieCastPoster.js @@ -4,7 +4,8 @@ import { icons } from 'Helpers/Props'; import IconButton from 'Components/Link/IconButton'; import Label from 'Components/Label'; import MovieHeadshot from 'Movie/MovieHeadshot'; -import styles from './MovieCastPoster.css'; +import EditNetImportModalConnector from 'Settings/NetImport/NetImport/EditNetImportModalConnector'; +import styles from '../MovieCreditPoster.css'; class MovieCastPoster extends Component { @@ -16,19 +17,24 @@ class MovieCastPoster extends Component { this.state = { hasPosterError: false, - isEditMovieModalOpen: false + isEditNetImportModalOpen: false }; } // // Listeners - onEditMoviePress = () => { - this.setState({ isEditMovieModalOpen: true }); + onEditNetImportPress = () => { + this.setState({ isEditNetImportModalOpen: true }); } - onEditMovieModalClose = () => { - this.setState({ isEditMovieModalOpen: false }); + onAddNetImportPress = () => { + this.props.onNetImportSelect(); + this.setState({ isEditNetImportModalOpen: true }); + } + + onEditNetImportModalClose = () => { + this.setState({ isEditNetImportModalOpen: false }); } onPosterLoad = () => { @@ -48,11 +54,12 @@ class MovieCastPoster extends Component { render() { const { - castName, + personName, character, images, posterWidth, - posterHeight + posterHeight, + netImportId } = this.props; const { @@ -68,12 +75,21 @@ class MovieCastPoster extends Component {
- {castName} + {personName}
}
- {castName} + {personName}
{character}
+ + ); } } MovieCastPoster.propTypes = { - castId: PropTypes.number.isRequired, - castName: PropTypes.string.isRequired, + tmdbId: PropTypes.number.isRequired, + personName: PropTypes.string.isRequired, character: PropTypes.string.isRequired, images: PropTypes.arrayOf(PropTypes.object).isRequired, posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired + posterHeight: PropTypes.number.isRequired, + netImportId: PropTypes.number.isRequired, + onNetImportSelect: PropTypes.func.isRequired +}; + +MovieCastPoster.defaultProps = { + netImportId: 0 }; export default MovieCastPoster; diff --git a/frontend/src/Movie/Details/Credits/Cast/MovieCastPostersConnector.js b/frontend/src/Movie/Details/Credits/Cast/MovieCastPostersConnector.js new file mode 100644 index 000000000..c1cf623ca --- /dev/null +++ b/frontend/src/Movie/Details/Credits/Cast/MovieCastPostersConnector.js @@ -0,0 +1,60 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import MovieCreditPosters from '../MovieCreditPosters'; +import MovieCastPoster from './MovieCastPoster'; +import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; + +function createMapStateToProps() { + return createSelector( + (state) => state.movieCredits.items, + (credits) => { + const cast = _.reduce(credits, (acc, credit) => { + if (credit.type === 'cast') { + acc.push(credit); + } + + return acc; + }, []); + + return { + items: cast + }; + } + ); +} + +const mapDispatchToProps = { + fetchRootFolders +}; + +class MovieCastPostersConnector extends Component { + + // + // Lifecycle + + componentDidMount() { + this.props.fetchRootFolders(); + } + + // + // Render + + render() { + + return ( + + ); + } +} + +MovieCastPostersConnector.propTypes = { + fetchRootFolders: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(MovieCastPostersConnector); diff --git a/frontend/src/Movie/Details/Crew/MovieCrewPoster.js b/frontend/src/Movie/Details/Credits/Crew/MovieCrewPoster.js similarity index 56% rename from frontend/src/Movie/Details/Crew/MovieCrewPoster.js rename to frontend/src/Movie/Details/Credits/Crew/MovieCrewPoster.js index 73142ff0c..23a5c3e5a 100644 --- a/frontend/src/Movie/Details/Crew/MovieCrewPoster.js +++ b/frontend/src/Movie/Details/Credits/Crew/MovieCrewPoster.js @@ -4,7 +4,8 @@ import { icons } from 'Helpers/Props'; import IconButton from 'Components/Link/IconButton'; import Label from 'Components/Label'; import MovieHeadshot from 'Movie/MovieHeadshot'; -import styles from './MovieCrewPoster.css'; +import EditNetImportModalConnector from 'Settings/NetImport/NetImport/EditNetImportModalConnector'; +import styles from '../MovieCreditPoster.css'; class MovieCrewPoster extends Component { @@ -16,19 +17,24 @@ class MovieCrewPoster extends Component { this.state = { hasPosterError: false, - isEditMovieModalOpen: false + isEditNetImportModalOpen: false }; } // // Listeners - onEditMoviePress = () => { - this.setState({ isEditMovieModalOpen: true }); + onEditNetImportPress = () => { + this.setState({ isEditNetImportModalOpen: true }); } - onEditMovieModalClose = () => { - this.setState({ isEditMovieModalOpen: false }); + onAddNetImportPress = () => { + this.props.onNetImportSelect(); + this.setState({ isEditNetImportModalOpen: true }); + } + + onEditNetImportModalClose = () => { + this.setState({ isEditNetImportModalOpen: false }); } onPosterLoad = () => { @@ -48,11 +54,12 @@ class MovieCrewPoster extends Component { render() { const { - crewName, + personName, job, images, posterWidth, - posterHeight + posterHeight, + netImportId } = this.props; const { @@ -68,12 +75,21 @@ class MovieCrewPoster extends Component {
- {crewName} + {personName}
}
- {crewName} + {personName}
{job}
+ + ); } } MovieCrewPoster.propTypes = { - crewId: PropTypes.number.isRequired, - crewName: PropTypes.string.isRequired, + tmdbId: PropTypes.number.isRequired, + personName: PropTypes.string.isRequired, job: PropTypes.string.isRequired, images: PropTypes.arrayOf(PropTypes.object).isRequired, posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired + posterHeight: PropTypes.number.isRequired, + netImportId: PropTypes.number.isRequired, + onNetImportSelect: PropTypes.func.isRequired +}; + +MovieCrewPoster.defaultProps = { + netImportId: 0 }; export default MovieCrewPoster; diff --git a/frontend/src/Movie/Details/Credits/Crew/MovieCrewPostersConnector.js b/frontend/src/Movie/Details/Credits/Crew/MovieCrewPostersConnector.js new file mode 100644 index 000000000..99ac4ec35 --- /dev/null +++ b/frontend/src/Movie/Details/Credits/Crew/MovieCrewPostersConnector.js @@ -0,0 +1,60 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import MovieCreditPosters from '../MovieCreditPosters'; +import MovieCrewPoster from './MovieCrewPoster'; +import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; + +function createMapStateToProps() { + return createSelector( + (state) => state.movieCredits.items, + (credits) => { + const crew = _.reduce(credits, (acc, credit) => { + if (credit.type === 'crew') { + acc.push(credit); + } + + return acc; + }, []); + + return { + items: crew + }; + } + ); +} + +const mapDispatchToProps = { + fetchRootFolders +}; + +class MovieCrewPostersConnector extends Component { + + // + // Lifecycle + + componentDidMount() { + this.props.fetchRootFolders(); + } + + // + // Render + + render() { + + return ( + + ); + } +} + +MovieCrewPostersConnector.propTypes = { + fetchRootFolders: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(MovieCrewPostersConnector); diff --git a/frontend/src/Movie/Details/Cast/MovieCastPoster.css b/frontend/src/Movie/Details/Credits/MovieCreditPoster.css similarity index 100% rename from frontend/src/Movie/Details/Cast/MovieCastPoster.css rename to frontend/src/Movie/Details/Credits/MovieCreditPoster.css diff --git a/frontend/src/Movie/Details/Credits/MovieCreditPosterConnector.js b/frontend/src/Movie/Details/Credits/MovieCreditPosterConnector.js new file mode 100644 index 000000000..e22db44fa --- /dev/null +++ b/frontend/src/Movie/Details/Credits/MovieCreditPosterConnector.js @@ -0,0 +1,58 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import createMovieCreditListSelector from 'Store/Selectors/createMovieCreditListSelector'; +import { selectNetImportSchema, setNetImportValue, setNetImportFieldValue } from 'Store/Actions/settingsActions'; + +function createMapStateToProps() { + return createMovieCreditListSelector(); +} + +const mapDispatchToProps = { + selectNetImportSchema, + setNetImportFieldValue, + setNetImportValue +}; + +class MovieCreditPosterConnector extends Component { + + // + // Listeners + + onNetImportSelect = () => { + this.props.selectNetImportSchema({ implementation: 'TMDbPersonImport', presetName: undefined }); + this.props.setNetImportFieldValue({ name: 'personId', value: this.props.tmdbId.toString() }); + this.props.setNetImportValue({ name: 'name', value: `${this.props.personName} - ${this.props.tmdbId}` }); + } + + // + // Render + + render() { + const { + tmdbId, + component: ItemComponent, + personName + } = this.props; + + return ( + + ); + } +} + +MovieCreditPosterConnector.propTypes = { + tmdbId: PropTypes.number.isRequired, + personName: PropTypes.string.isRequired, + component: PropTypes.elementType.isRequired, + selectNetImportSchema: PropTypes.func.isRequired, + setNetImportFieldValue: PropTypes.func.isRequired, + setNetImportValue: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(MovieCreditPosterConnector); diff --git a/frontend/src/Movie/Details/Cast/MovieCastPosters.css b/frontend/src/Movie/Details/Credits/MovieCreditPosters.css similarity index 100% rename from frontend/src/Movie/Details/Cast/MovieCastPosters.css rename to frontend/src/Movie/Details/Credits/MovieCreditPosters.css diff --git a/frontend/src/Movie/Details/Cast/MovieCastPosters.js b/frontend/src/Movie/Details/Credits/MovieCreditPosters.js similarity index 87% rename from frontend/src/Movie/Details/Cast/MovieCastPosters.js rename to frontend/src/Movie/Details/Credits/MovieCreditPosters.js index 6ae16a533..4031c78ed 100644 --- a/frontend/src/Movie/Details/Cast/MovieCastPosters.js +++ b/frontend/src/Movie/Details/Credits/MovieCreditPosters.js @@ -4,8 +4,8 @@ import { Grid, WindowScroller } from 'react-virtualized'; import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; import dimensions from 'Styles/Variables/dimensions'; import Measure from 'Components/Measure'; -import MovieCastPoster from './MovieCastPoster'; -import styles from './MovieCastPosters.css'; +import MovieCreditPosterConnector from './MovieCreditPosterConnector'; +import styles from './MovieCreditPosters.css'; // Poster container dimensions const columnPadding = parseInt(dimensions.movieIndexColumnPadding); @@ -47,7 +47,7 @@ function calculatePosterHeight(posterWidth) { return Math.ceil((250 / 170) * posterWidth); } -class MovieCastPosters extends Component { +class MovieCreditPosters extends Component { // // Lifecycle @@ -70,7 +70,7 @@ class MovieCastPosters extends Component { componentDidUpdate(prevProps, prevState) { const { - cast + items } = this.props; const { @@ -85,7 +85,7 @@ class MovieCastPosters extends Component { prevState.columnWidth !== columnWidth || prevState.columnCount !== columnCount || prevState.rowHeight !== rowHeight || - hasDifferentItemsOrOrder(prevProps.cast, cast))) { + hasDifferentItemsOrOrder(prevProps.items, items))) { // recomputeGridSize also forces Grid to discard its cache of rendered cells this._grid.recomputeGridSize(); } @@ -119,7 +119,8 @@ class MovieCastPosters extends Component { cellRenderer = ({ key, rowIndex, columnIndex, style }) => { const { - cast + items, + itemComponent } = this.props; const { @@ -129,7 +130,7 @@ class MovieCastPosters extends Component { } = this.state; const movieIdx = rowIndex * columnCount + columnIndex; - const movie = cast[movieIdx]; + const movie = items[movieIdx]; if (!movie) { return null; @@ -141,12 +142,14 @@ class MovieCastPosters extends Component { key={key} style={style} > - @@ -166,7 +169,7 @@ class MovieCastPosters extends Component { render() { const { - cast + items } = this.props; const { @@ -176,7 +179,7 @@ class MovieCastPosters extends Component { rowHeight } = this.state; - const rowCount = Math.ceil(cast.length / columnCount); + const rowCount = Math.ceil(items.length / columnCount); return ( acc + height, 0); -} - -function calculatePosterHeight(posterWidth) { - return Math.ceil((250 / 170) * posterWidth); -} - -class MovieCrewPosters extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - width: 0, - columnWidth: 182, - columnCount: 1, - posterWidth: 162, - posterHeight: 238, - rowHeight: calculateRowHeight(238, props.isSmallScreen) - }; - - this._isInitialized = false; - this._grid = null; - } - - componentDidUpdate(prevProps, prevState) { - const { - crew - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - if (this._grid && - (prevState.width !== width || - prevState.columnWidth !== columnWidth || - prevState.columnCount !== columnCount || - prevState.rowHeight !== rowHeight || - hasDifferentItemsOrOrder(prevProps.crew, crew))) { - // recomputeGridSize also forces Grid to discard its cache of rendered cells - this._grid.recomputeGridSize(); - } - } - - // - // Control - - setGridRef = (ref) => { - this._grid = ref; - } - - calculateGrid = (width = this.state.width, isSmallScreen) => { - - const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding; - const columnWidth = calculateColumnWidth(width, 'small', isSmallScreen); - const columnCount = Math.max(Math.floor(width / columnWidth), 1); - const posterWidth = columnWidth - padding; - const posterHeight = calculatePosterHeight(posterWidth); - const rowHeight = calculateRowHeight(posterHeight, isSmallScreen); - - this.setState({ - width, - columnWidth, - columnCount, - posterWidth, - posterHeight, - rowHeight - }); - } - - cellRenderer = ({ key, rowIndex, columnIndex, style }) => { - const { - crew - } = this.props; - - const { - posterWidth, - posterHeight, - columnCount - } = this.state; - - const movieIdx = rowIndex * columnCount + columnIndex; - const movie = crew[movieIdx]; - - if (!movie) { - return null; - } - - return ( -
- -
- ); - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.calculateGrid(width, this.props.isSmallScreen); - } - - // - // Render - - render() { - const { - crew - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - const rowCount = Math.ceil(crew.length / columnCount); - - return ( - - - {({ height, registerChild, onChildScroll, scrollTop }) => { - if (!height) { - return
; - } - - return ( -
- -
- ); - } - } - - - ); - } -} - -MovieCrewPosters.propTypes = { - crew: PropTypes.arrayOf(PropTypes.object).isRequired, - isSmallScreen: PropTypes.bool.isRequired -}; - -export default MovieCrewPosters; diff --git a/frontend/src/Movie/Details/Crew/MovieCrewPostersConnector.js b/frontend/src/Movie/Details/Crew/MovieCrewPostersConnector.js deleted file mode 100644 index f23ee56b5..000000000 --- a/frontend/src/Movie/Details/Crew/MovieCrewPostersConnector.js +++ /dev/null @@ -1,25 +0,0 @@ -import _ from 'lodash'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import MovieCrewPosters from './MovieCrewPosters'; - -function createMapStateToProps() { - return createSelector( - (state) => state.moviePeople.items, - (people) => { - const crew = _.reduce(people, (acc, person) => { - if (person.type === 'crew') { - acc.push(person); - } - - return acc; - }, []); - - return { - crew - }; - } - ); -} - -export default connect(createMapStateToProps)(MovieCrewPosters); diff --git a/frontend/src/Movie/Details/MovieDetails.js b/frontend/src/Movie/Details/MovieDetails.js index 277e35542..6e38b67e1 100644 --- a/frontend/src/Movie/Details/MovieDetails.js +++ b/frontend/src/Movie/Details/MovieDetails.js @@ -31,8 +31,8 @@ import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; import MovieHistoryTable from 'Movie/History/MovieHistoryTable'; import MovieTitlesTable from './Titles/MovieTitlesTable'; -import MovieCastPostersConnector from './Cast/MovieCastPostersConnector'; -import MovieCrewPostersConnector from './Crew/MovieCrewPostersConnector'; +import MovieCastPostersConnector from './Credits/Cast/MovieCastPostersConnector'; +import MovieCrewPostersConnector from './Credits/Crew/MovieCrewPostersConnector'; import MovieAlternateTitles from './MovieAlternateTitles'; import MovieDetailsLinks from './MovieDetailsLinks'; import InteractiveSearchTable from 'InteractiveSearch/InteractiveSearchTable'; @@ -181,7 +181,7 @@ class MovieDetails extends Component { isPopulated, isSmallScreen, movieFilesError, - moviePeopleError, + movieCreditsError, hasMovieFiles, previousMovie, nextMovie, @@ -464,12 +464,12 @@ class MovieDetails extends Component {
{ - !isPopulated && !movieFilesError && !moviePeopleError && + !isPopulated && !movieFilesError && !movieCreditsError && } { - !isFetching && movieFilesError && !moviePeopleError && + !isFetching && movieFilesError && !movieCreditsError &&
Loading movie files failed
} @@ -629,7 +629,7 @@ MovieDetails.propTypes = { isPopulated: PropTypes.bool.isRequired, isSmallScreen: PropTypes.bool.isRequired, movieFilesError: PropTypes.object, - moviePeopleError: PropTypes.object, + movieCreditsError: PropTypes.object, hasMovieFiles: PropTypes.bool.isRequired, previousMovie: PropTypes.object.isRequired, nextMovie: PropTypes.object.isRequired, diff --git a/frontend/src/Movie/Details/MovieDetailsConnector.js b/frontend/src/Movie/Details/MovieDetailsConnector.js index 36dd4ac09..7584531ca 100644 --- a/frontend/src/Movie/Details/MovieDetailsConnector.js +++ b/frontend/src/Movie/Details/MovieDetailsConnector.js @@ -9,10 +9,11 @@ import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector'; import createCommandsSelector from 'Store/Selectors/createCommandsSelector'; import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; import { fetchMovieFiles, clearMovieFiles } from 'Store/Actions/movieFileActions'; -import { fetchMoviePeople, clearMoviePeople } from 'Store/Actions/moviePeopleActions'; +import { fetchMovieCredits, clearMovieCredits } from 'Store/Actions/movieCreditsActions'; import { toggleMovieMonitored } from 'Store/Actions/movieActions'; import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions'; import { clearReleases, cancelFetchReleases } from 'Store/Actions/releaseActions'; +import { fetchNetImportSchema } from 'Store/Actions/settingsActions'; import { executeCommand } from 'Store/Actions/commandActions'; import * as commandNames from 'Commands/commandNames'; import MovieDetails from './MovieDetails'; @@ -41,19 +42,19 @@ const selectMovieFiles = createSelector( } ); -const selectMoviePeople = createSelector( - (state) => state.moviePeople, - (moviePeople) => { +const selectMovieCredits = createSelector( + (state) => state.movieCredits, + (movieCredits) => { const { isFetching, isPopulated, error - } = moviePeople; + } = movieCredits; return { - isMoviePeopleFetching: isFetching, - isMoviePeoplePopulated: isPopulated, - moviePeopleError: error + isMovieCreditsFetching: isFetching, + isMovieCreditsPopulated: isPopulated, + movieCreditsError: error }; } ); @@ -62,11 +63,11 @@ function createMapStateToProps() { return createSelector( (state, { titleSlug }) => titleSlug, selectMovieFiles, - selectMoviePeople, + selectMovieCredits, createAllMoviesSelector(), createCommandsSelector(), createDimensionsSelector(), - (titleSlug, movieFiles, moviePeople, allMovies, commands, dimensions) => { + (titleSlug, movieFiles, movieCredits, allMovies, commands, dimensions) => { const sortedMovies = _.orderBy(allMovies, 'sortTitle'); const movieIndex = _.findIndex(sortedMovies, { titleSlug }); const movie = sortedMovies[movieIndex]; @@ -84,10 +85,10 @@ function createMapStateToProps() { } = movieFiles; const { - isMoviePeopleFetching, - isMoviePeoplePopulated, - moviePeopleError - } = moviePeople; + isMovieCreditsFetching, + isMovieCreditsPopulated, + movieCreditsError + } = movieCredits; const previousMovie = sortedMovies[movieIndex - 1] || _.last(sortedMovies); const nextMovie = sortedMovies[movieIndex + 1] || _.first(sortedMovies); @@ -106,8 +107,8 @@ function createMapStateToProps() { isRenamingMovieCommand.body.movieIds.indexOf(movie.id) > -1 ); - const isFetching = isMovieFilesFetching && isMoviePeopleFetching; - const isPopulated = isMovieFilesPopulated && isMoviePeoplePopulated; + const isFetching = isMovieFilesFetching && isMovieCreditsFetching; + const isPopulated = isMovieFilesPopulated && isMovieCreditsPopulated; const alternateTitles = _.reduce(movie.alternateTitles, (acc, alternateTitle) => { acc.push(alternateTitle.title); return acc; @@ -125,7 +126,7 @@ function createMapStateToProps() { isFetching, isPopulated, movieFilesError, - moviePeopleError, + movieCreditsError, hasMovieFiles, sizeOnDisk, previousMovie, @@ -139,10 +140,11 @@ function createMapStateToProps() { const mapDispatchToProps = { fetchMovieFiles, clearMovieFiles, - fetchMoviePeople, - clearMoviePeople, + fetchMovieCredits, + clearMovieCredits, clearReleases, cancelFetchReleases, + fetchNetImportSchema, toggleMovieMonitored, fetchQueueDetails, clearQueueDetails, @@ -198,14 +200,15 @@ class MovieDetailsConnector extends Component { const movieId = this.props.id; this.props.fetchMovieFiles({ movieId }); - this.props.fetchMoviePeople({ movieId }); + this.props.fetchMovieCredits({ movieId }); this.props.fetchQueueDetails({ movieId }); + this.props.fetchNetImportSchema(); } unpopulate = () => { this.props.cancelFetchReleases(); this.props.clearMovieFiles(); - this.props.clearMoviePeople(); + this.props.clearMovieCredits(); this.props.clearQueueDetails(); this.props.clearReleases(); } @@ -260,13 +263,14 @@ MovieDetailsConnector.propTypes = { isSmallScreen: PropTypes.bool.isRequired, fetchMovieFiles: PropTypes.func.isRequired, clearMovieFiles: PropTypes.func.isRequired, - fetchMoviePeople: PropTypes.func.isRequired, - clearMoviePeople: PropTypes.func.isRequired, + fetchMovieCredits: PropTypes.func.isRequired, + clearMovieCredits: PropTypes.func.isRequired, clearReleases: PropTypes.func.isRequired, cancelFetchReleases: PropTypes.func.isRequired, toggleMovieMonitored: PropTypes.func.isRequired, fetchQueueDetails: PropTypes.func.isRequired, clearQueueDetails: PropTypes.func.isRequired, + fetchNetImportSchema: PropTypes.func.isRequired, executeCommand: PropTypes.func.isRequired }; diff --git a/frontend/src/Store/Selectors/createMovieCreditListSelector.js b/frontend/src/Store/Selectors/createMovieCreditListSelector.js new file mode 100644 index 000000000..a98b1728c --- /dev/null +++ b/frontend/src/Store/Selectors/createMovieCreditListSelector.js @@ -0,0 +1,37 @@ +import _ from 'lodash'; +import { createSelector } from 'reselect'; + +function createMovieCreditListSelector() { + return createSelector( + (state, { tmdbId }) => tmdbId, + (state) => state.settings.netImports.items, + (tmdbId, netImports) => { + const netImportIds = _.reduce(netImports, (acc, list) => { + if (list.implementation === 'TMDbPersonImport') { + const personIdField = list.fields.find((field) => { + return field.name === 'personId'; + }); + + if (personIdField && parseInt(personIdField.value) === tmdbId) { + acc.push(list); + return acc; + } + } + + return acc; + }, []); + + let netImportId = 0; + + if (netImportIds.length > 0) { + netImportId = netImportIds[0].id; + } + + return { + netImportId + }; + } + ); +} + +export default createMovieCreditListSelector;