diff --git a/src/public/js/actions/actionCreators.js b/src/public/js/actions/actionCreators.js index 0ef97ca..1dc6e68 100644 --- a/src/public/js/actions/actionCreators.js +++ b/src/public/js/actions/actionCreators.js @@ -92,6 +92,13 @@ export function selectMovie(imdbId) { } } +export function getMovieExploreOptions() { + return request( + 'MOVIE_GET_EXPLORE_OPTIONS', + configureAxios().get('/movies/explore/options') + ) +} + export function deleteMovieFromStore(imdbId) { return { type: 'DELETE_MOVIE', @@ -106,6 +113,13 @@ export function searchMovies(search) { ) } +export function exploreMovies(source, category) { + return request( + 'EXPLORE_MOVIES', + configureAxios().get(`/movies/explore?source=${encodeURI(source)}&category=${encodeURI(category)}`) + ) +} + export function getMovieDetails(imdbId) { return request( 'MOVIE_GET_DETAILS', @@ -251,6 +265,20 @@ export function updateShowWishlistStore(imdbId, wishlisted, season = null, episo } } +export function exploreShows(source, category) { + return request( + 'EXPLORE_SHOWS', + configureAxios().get(`/shows/explore?source=${encodeURI(source)}&category=${encodeURI(category)}`) + ) +} + +export function getShowExploreOptions() { + return request( + 'SHOW_GET_EXPLORE_OPTIONS', + configureAxios().get('/shows/explore/options') + ) +} + export function selectShow(imdbId) { return { type: 'SELECT_SHOW', diff --git a/src/public/js/app.js b/src/public/js/app.js index 5bde321..6000e21 100644 --- a/src/public/js/app.js +++ b/src/public/js/app.js @@ -37,7 +37,7 @@ import UserSignUp from './components/users/signup' class Main extends React.Component { componentWillMount() { - this.props.isUserLoggedIn() + this.props.isUserLoggedIn(); } render() { return ( @@ -77,52 +77,37 @@ const UserIsAuthenticated = UserAuthWrapper({ }) // TODO find a better way -const MovieListPopular = (props) => ( - -) const MovieListPolochon = (props) => ( ) const MovieListWishlisted = (props) => ( ) -const MovieListSearch = (props) => ( - -) -const ShowListPopular = (props) => ( - -) const ShowListPolochon = (props) => ( ) const ShowListWishlisted = (props) => ( ) -const ShowDetailsView = (props) => ( - -) -const ShowListSearch = (props) => ( - -) ReactDOM.render(( - + - - + + - - + - + + diff --git a/src/public/js/components/list/explorerOptions.js b/src/public/js/components/list/explorerOptions.js new file mode 100644 index 0000000..9272803 --- /dev/null +++ b/src/public/js/components/list/explorerOptions.js @@ -0,0 +1,127 @@ +import React from 'react' +import { Form, FormGroup, FormControl, ControlLabel } from 'react-bootstrap' + +export default class ExplorerOptions extends React.Component { + constructor(props) { + super(props); + let source = null; + let category = null; + let categories = []; + + // Check if the options are present + if (Object.keys(this.props.options).length === 0) { + // Fetch options + this.props.fetchOptions(); + // Explore + this.props.explore(this.props.params.source, this.props.params.category); + } else { + source = this.props.params.source; + category = this.props.params.category; + categories = this.props.options[this.props.params.source]; + } + + this.state = { + selectedSource: source, + selectedCategory: category, + categories: categories, + }; + this.handleSourceChange = this.handleSourceChange.bind(this); + this.handleCategoryChange = this.handleCategoryChange.bind(this); + } + handleSourceChange(event) { + let source = event.target.value; + let category = this.props.options[event.target.value][0]; + this.setState({ + selectedSource: source, + selectedCategory: category, + categories: this.props.options[source], + }); + this.props.router.push(`/${this.props.type}/explore/${source}/${category}`); + } + handleCategoryChange(event) { + this.setState({ selectedCategory: event.target.value }); + this.props.router.push(`/${this.props.type}/explore/${this.state.selectedSource}/${event.target.value}`); + } + componentWillUpdate(nextProps, nextState) { + // Check props + if (!nextProps.params.source + || !nextProps.params.category + || (nextProps.params.source === "") + || (nextProps.params.category === "")) { + return + } + + // Explore params changed + if ((this.props.params.source !== nextProps.params.source) + || (this.props.params.category !== nextProps.params.category)) { + this.props.explore(nextProps.params.source, nextProps.params.category); + } + + // State must be updated + if ((this.state.selectedSource !== nextProps.params.source) + || (this.state.selectedCategory !== nextProps.params.category)) { + this.setState({ + selectedSource: nextProps.params.source, + selectedCategory: nextProps.params.category, + categories: nextProps.options[nextProps.params.source], + }); + } + } + render() { + // Should this componennt be displayed + if (!this.props.display) { + return null; + } + + // Options are not yet fetched + if (Object.keys(this.props.options).length === 0) { + return null; + } + + // State is not yet set + if (!this.state.selectedSource && !this.state.selectedCategory) { + return null; + } + + return ( +
+
+
+
+
+ + Source + + {Object.keys(this.props.options).map(function(source) { + return () + })} + + +
+
+ + Category + + {this.state.categories.map(function(category) { + return () + }, this)} + + +
+
+
+
+
+ ); + } +} diff --git a/src/public/js/components/list/filter.js b/src/public/js/components/list/filter.js index c1bf4bd..b1dca71 100644 --- a/src/public/js/components/list/filter.js +++ b/src/public/js/components/list/filter.js @@ -2,6 +2,10 @@ import React from 'react' import { Control, Form } from 'react-redux-form'; export default function ListFilter(props) { + if (!props.display) { + return null; + } + if (props.listSize === 0) { return null; } diff --git a/src/public/js/components/list/posters.js b/src/public/js/components/list/posters.js index bb80d20..367bccb 100644 --- a/src/public/js/components/list/posters.js +++ b/src/public/js/components/list/posters.js @@ -4,6 +4,7 @@ import fuzzy from 'fuzzy'; import InfiniteScroll from 'react-infinite-scroller'; import ListFilter from './filter' +import ExplorerOptions from './explorerOptions' import ListPoster from './poster' export default class ListPosters extends React.Component { @@ -49,13 +50,33 @@ export default class ListPosters extends React.Component { elmts = elmts.slice(0, this.state.items); } + // Chose when to display filter / explore options + let displayFilter = true; + if (this.props.params + && this.props.params.category + && this.props.params.category !== "" + && this.props.params.source + && this.props.params.source !== "") { + displayFilter = false; + } + return (
+ {elmts.length === 0 &&
diff --git a/src/public/js/components/movies/list.js b/src/public/js/components/movies/list.js index 4eb7adc..c3421aa 100644 --- a/src/public/js/components/movies/list.js +++ b/src/public/js/components/movies/list.js @@ -41,25 +41,42 @@ function MovieButtons(props) { } export default class MovieList extends React.Component { - componentWillMount() { - if (this.props.moviesUrl) { - this.props.fetchMovies(this.props.moviesUrl); - } else if (this.props.params && this.props.params.search != "") { - this.props.searchMovies({ - key: this.props.params.search + handleParams(props = this.props) { + // Check if the URL to fetch is in the props + if (props.moviesUrl) { + this.props.fetchMovies(props.moviesUrl); + return + } + + // Check for URL parameters + if (!props.params) { + return + } + + // Search param + if (props.params.search && props.params.search !== "") { + props.searchMovies({ + key: props.params.search }); + return } } + componentWillMount() { + this.handleParams(); + } componentWillUpdate(nextProps, nextState) { - if (!nextProps.params || nextProps.params.search === "") { + // No params + if (!nextProps.params) { return } - if (this.props.params.search === nextProps.params.search) { + + // Search field changed + if (this.props.params.search + && (this.props.params.search !== nextProps.params.search) + && (nextProps.params.search !== "")) { + this.handleParams(nextProps); return } - this.props.searchMovies({ - key: nextProps.params.search - }); } render() { const movies = this.props.movieStore.movies; @@ -79,14 +96,19 @@ export default class MovieList extends React.Component {
{selectedMovie && diff --git a/src/public/js/components/navbar.js b/src/public/js/components/navbar.js index 29961f9..97cc8ac 100644 --- a/src/public/js/components/navbar.js +++ b/src/public/js/components/navbar.js @@ -85,8 +85,8 @@ function MoviesDropdown(props) { return(