diff --git a/src/public/js/actions/actionCreators.js b/src/public/js/actions/actionCreators.js index c630e2a..8fe7a77 100644 --- a/src/public/js/actions/actionCreators.js +++ b/src/public/js/actions/actionCreators.js @@ -124,6 +124,38 @@ export function deleteMovie(imdbId) { ) } +export function addMovieToWishlist(imdbId) { + return request( + 'MOVIE_ADD_TO_WISHLIST', + configureAxios().post(`/wishlist/movies/${imdbId}`), + [ + addAlertOk("Movie added to the wishlist"), + updateMovieWishlistStore(imdbId, true), + ], + ) +} + +export function deleteMovieFromWishlist(imdbId) { + return request( + 'MOVIE_DELETE_FROM_WISHLIST', + configureAxios().delete(`/wishlist/movies/${imdbId}`), + [ + addAlertOk("Movie deleted from the wishlist"), + updateMovieWishlistStore(imdbId, false), + ], + ) +} + +export function updateMovieWishlistStore(imdbId, wishlisted) { + return { + type: 'MOVIE_UPDATE_STORE_WISHLIST', + payload: { + imdbId, + wishlisted, + } + } +} + export function fetchMovies(url) { return request( 'MOVIE_LIST_FETCH', @@ -156,6 +188,43 @@ export function fetchShowDetails(imdbId) { ) } +export function addShowToWishlist(imdbId, season = null, episode = null) { + return request( + 'SHOW_ADD_TO_WISHLIST', + configureAxios().post(`/wishlist/shows/${imdbId}`, { + season: season, + episode: episode, + }), + [ + addAlertOk("Show added to the wishlist"), + updateShowWishlistStore(imdbId, true, season, episode), + ], + ) +} + +export function deleteShowFromWishlist(imdbId) { + return request( + 'SHOW_DELETE_FROM_WISHLIST', + configureAxios().delete(`/wishlist/shows/${imdbId}`), + [ + addAlertOk("Show deleted from the wishlist"), + updateShowWishlistStore(imdbId, false), + ], + ) +} + +export function updateShowWishlistStore(imdbId, wishlisted, season = null, episode = null) { + return { + type: 'SHOW_UPDATE_STORE_WISHLIST', + payload: { + wishlisted: wishlisted, + imdbId, + season, + episode, + } + } +} + export function selectShow(imdbId) { return { type: 'SELECT_SHOW', diff --git a/src/public/js/components/buttons/actions.js b/src/public/js/components/buttons/actions.js new file mode 100644 index 0000000..eecf765 --- /dev/null +++ b/src/public/js/components/buttons/actions.js @@ -0,0 +1,87 @@ +import React from 'react' + +import { MenuItem } from 'react-bootstrap' + +export class WishlistButton extends React.Component { + constructor(props) { + super(props); + this.handleClick = this.handleClick.bind(this); + } + handleClick(e) { + e.preventDefault(); + if (this.props.wishlisted) { + this.props.deleteFromWishlist(this.props.resourceId); + } else { + this.props.addToWishlist(this.props.resourceId); + } + } + render() { + if (this.props.wishlisted) { + return ( + + + Delete from wishlist + + + ); + } else { + return ( + + + Add to wishlist + + + ); + } + } +} + +export class DeleteButton extends React.Component { + constructor(props) { + super(props); + this.handleClick = this.handleClick.bind(this); + } + handleClick(e) { + e.preventDefault(); + this.props.deleteFunc(this.props.resourceId); + } + render() { + return ( + + + Delete + + + ); + } +} + +export class RefreshButton extends React.Component { + constructor(props) { + super(props); + this.handleClick = this.handleClick.bind(this); + } + handleClick(e) { + e.preventDefault(); + if (this.props.fetching) { + return + } + this.props.getDetails(this.props.resourceId); + } + render() { + return ( + + {this.props.fetching || + + Refresh + + } + {this.props.fetching && + + Refreshing + + } + + ); + } +} diff --git a/src/public/js/components/movies/actions.js b/src/public/js/components/movies/actions.js index e78e634..bc61e4d 100644 --- a/src/public/js/components/movies/actions.js +++ b/src/public/js/components/movies/actions.js @@ -1,72 +1,29 @@ import React from 'react' -import { DropdownButton, MenuItem } from 'react-bootstrap' +import { WishlistButton, DeleteButton, RefreshButton } from '../buttons/actions' +import { DropdownButton } from 'react-bootstrap' export default function ActionsButton(props) { return ( {(props.isUserAdmin && props.hasMovie) && } + ); } - -class RefreshButton extends React.Component { - constructor(props) { - super(props); - this.handleClick = this.handleClick.bind(this); - } - handleClick(e) { - e.preventDefault(); - if (this.props.fetching) { - return - } - this.props.getDetails(this.props.movieId); - } - render() { - return ( - - {this.props.fetching || - - Refresh - - } - {this.props.fetching && - - Refreshing - - } - - ); - } -} - -class DeleteButton extends React.Component { - constructor(props) { - super(props); - this.handleClick = this.handleClick.bind(this); - } - handleClick(e) { - e.preventDefault(); - this.props.deleteMovie(this.props.movieId); - } - render() { - return ( - - - Delete - - - ); - } -} diff --git a/src/public/js/components/movies/list.js b/src/public/js/components/movies/list.js index 37866b7..ece9a55 100644 --- a/src/public/js/components/movies/list.js +++ b/src/public/js/components/movies/list.js @@ -31,6 +31,9 @@ function MovieButtons(props) { deleteMovie={props.deleteMovie} isUserAdmin={props.isUserAdmin} hasMovie={hasMovie} + wishlisted={props.movie.wishlisted} + addToWishlist={props.addToWishlist} + deleteFromWishlist={props.deleteFromWishlist} /> @@ -97,6 +100,8 @@ export default class MovieList extends React.Component { addTorrent={this.props.addTorrent} deleteMovie={this.props.deleteMovie} isUserAdmin={this.props.userStore.isAdmin} + addToWishlist={this.props.addMovieToWishlist} + deleteFromWishlist={this.props.deleteMovieFromWishlist} /> } diff --git a/src/public/js/components/shows/list.js b/src/public/js/components/shows/list.js index 8b0703f..3704260 100644 --- a/src/public/js/components/shows/list.js +++ b/src/public/js/components/shows/list.js @@ -1,23 +1,9 @@ import React from 'react' -import { Link } from 'react-router' import ListDetails from '../list/details' import ListPosters from '../list/posters' import Loader from '../loader/loader' - -function ShowButtons(props) { - const imdbLink = `http://www.imdb.com/title/${props.show.imdb_id}`; - return ( -
- - IMDB - - - Details - -
- ); -} +import ShowButtons from './listButtons' export default class ShowList extends React.Component { componentWillMount() { @@ -68,7 +54,11 @@ export default class ShowList extends React.Component { /> {selectedShow && - + } diff --git a/src/public/js/components/shows/listButtons.js b/src/public/js/components/shows/listButtons.js new file mode 100644 index 0000000..d7baed3 --- /dev/null +++ b/src/public/js/components/shows/listButtons.js @@ -0,0 +1,39 @@ +import React from 'react' + +import { Link } from 'react-router' +import { DropdownButton } from 'react-bootstrap' + +import { WishlistButton } from '../buttons/actions' + +export default function ShowButtons(props) { + const imdbLink = `http://www.imdb.com/title/${props.show.imdb_id}`; + return ( +
+ + + IMDB + + + Details + +
+ ); +} + +function ActionsButton(props) { + let wishlisted = (props.show.tracked_season !== null && props.show.tracked_episode !== null); + return ( + + + + ); +} diff --git a/src/public/js/reducers/movies.js b/src/public/js/reducers/movies.js index 83f9bd1..408967d 100644 --- a/src/public/js/reducers/movies.js +++ b/src/public/js/reducers/movies.js @@ -39,17 +39,17 @@ export default function movieStore(state = defaultState, action) { fetchingDetails: true, }) case 'MOVIE_GET_DETAILS_FULFILLED': - let movies = state.movies.slice(); - let index = movies.map((el) => el.imdb_id).indexOf(action.payload.data.imdb_id); - movies[index] = action.payload.data; return Object.assign({}, state, { - movies: movies, + movies: updateMovieDetails(state.movies.slice(), action.payload.data.imdb_id, action.payload.data), fetchingDetails: false, }) + case 'MOVIE_UPDATE_STORE_WISHLIST': + return Object.assign({}, state, { + movies: updateStoreWishlist(state.movies.slice(), action.payload.imdbId, action.payload.wishlisted), + }) case 'DELETE_MOVIE': return Object.assign({}, state, { movies: state.movies.filter((e) => (e.imdb_id !== action.imdbId)), - fetchingDetails: false, }) case 'SELECT_MOVIE': // Don't select the movie if we're fetching another movie's details @@ -64,3 +64,15 @@ export default function movieStore(state = defaultState, action) { return state } } + +function updateMovieDetails(movies, imdbId, data) { + let index = movies.map((el) => el.imdb_id).indexOf(imdbId); + movies[index] = data; + return movies +} + +function updateStoreWishlist(movies, imdbId, wishlisted) { + let index = movies.map((el) => el.imdb_id).indexOf(imdbId); + movies[index].wishlisted = wishlisted; + return movies +} diff --git a/src/public/js/reducers/shows.js b/src/public/js/reducers/shows.js index e18b4b5..bc32e30 100644 --- a/src/public/js/reducers/shows.js +++ b/src/public/js/reducers/shows.js @@ -45,6 +45,10 @@ export default function showStore(state = defaultState, action) { shows: action.payload.data, loading: false, }) + case 'SHOW_UPDATE_STORE_WISHLIST': + return Object.assign({}, state, { + shows: updateStoreWishlist(state.shows.slice(), action.payload), + }) case 'SELECT_SHOW': // Don't select the show if we're fetching another show's details if (state.fetchingDetails) { @@ -102,3 +106,20 @@ function sortEpisodes(show) { return show; } + +function updateStoreWishlist(shows, payload) { + let index = shows.map((el) => el.imdb_id).indexOf(payload.imdbId); + let season = payload.season; + let episode = payload.episode; + if (payload.wishlisted) { + if (season === null) { + season = 0; + } + if (episode === null) { + episode = 0; + } + } + shows[index].tracked_season = season; + shows[index].tracked_episode = episode; + return shows +}