Merge branch 'stuff' into 'master'

Stuff

See merge request !44
This commit is contained in:
Lucas 2017-02-01 13:25:45 +00:00
commit 703411762f
7 changed files with 129 additions and 2 deletions

View File

@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"github.com/gorilla/mux" "github.com/gorilla/mux"
customError "github.com/odwrtw/errors"
"github.com/odwrtw/papi" "github.com/odwrtw/papi"
polochon "github.com/odwrtw/polochon/lib" polochon "github.com/odwrtw/polochon/lib"
"github.com/odwrtw/polochon/modules/pam" "github.com/odwrtw/polochon/modules/pam"
@ -311,7 +312,8 @@ func EpisodeDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request,
return env.RenderError(w, err) return env.RenderError(w, err)
} }
if err := e.GetTorrents(env, force); err != nil { err = e.GetTorrents(env, force)
if err != nil && customError.IsFatal(err) {
return env.RenderError(w, err) return env.RenderError(w, err)
} }

View File

@ -181,6 +181,32 @@ export function searchShows(search) {
) )
} }
export function getShowDetails(imdbId) {
return request(
'SHOW_GET_DETAILS',
configureAxios().post(`/shows/${imdbId}/refresh`)
)
}
export function getEpisodeDetails(imdbId, season, episode) {
return request(
'EPISODE_GET_DETAILS',
configureAxios().post(`/shows/${imdbId}/seasons/${season}/episodes/${episode}`),
)
}
export function updateEpisodeDetailsStore(imdbId, season, episode) {
return {
type: 'EPISODE_GET_DETAILS',
payload: {
imdbId,
season,
episode,
},
}
}
export function fetchShowDetails(imdbId) { export function fetchShowDetails(imdbId) {
return request( return request(
'SHOW_FETCH_DETAILS', 'SHOW_FETCH_DETAILS',

View File

@ -65,6 +65,7 @@ export default class ListPosters extends React.Component {
<InfiniteScroll <InfiniteScroll
hasMore={this.state.hasMore} hasMore={this.state.hasMore}
loadMore={this.loadMore} loadMore={this.loadMore}
className="row"
> >
{elmts.map(function(el, index) { {elmts.map(function(el, index) {
const selected = (el.imdb_id === this.props.selectedImdbId) ? true : false; const selected = (el.imdb_id === this.props.selectedImdbId) ? true : false;

View File

@ -23,6 +23,8 @@ export default class ShowDetails extends React.Component {
data={this.props.showStore.show} data={this.props.showStore.show}
addTorrent={this.props.addTorrent} addTorrent={this.props.addTorrent}
addToWishlist={this.props.addShowToWishlist} addToWishlist={this.props.addShowToWishlist}
getEpisodeDetails={this.props.getEpisodeDetails}
updateEpisodeDetailsStore={this.props.updateEpisodeDetailsStore}
/> />
</div> </div>
); );
@ -94,6 +96,8 @@ function SeasonsList(props){
data={season} data={season}
addTorrent={props.addTorrent} addTorrent={props.addTorrent}
addToWishlist={props.addToWishlist} addToWishlist={props.addToWishlist}
getEpisodeDetails={props.getEpisodeDetails}
updateEpisodeDetailsStore={props.updateEpisodeDetailsStore}
/> />
</div> </div>
) )
@ -138,6 +142,8 @@ class Season extends React.Component {
data={episode} data={episode}
addTorrent={this.props.addTorrent} addTorrent={this.props.addTorrent}
addToWishlist={this.props.addToWishlist} addToWishlist={this.props.addToWishlist}
getEpisodeDetails={this.props.getEpisodeDetails}
updateEpisodeDetailsStore={this.props.updateEpisodeDetailsStore}
/> />
) )
}, this)} }, this)}
@ -173,6 +179,11 @@ function Episode(props) {
) )
})} })}
<DownloadButton data={props.data}/> <DownloadButton data={props.data}/>
<GetDetailsButton
data={props.data}
getEpisodeDetails={props.getEpisodeDetails}
updateEpisodeDetailsStore={props.updateEpisodeDetailsStore}
/>
</span> </span>
</td> </td>
</tr> </tr>
@ -297,3 +308,36 @@ function DownloadButton(props) {
</span> </span>
); );
} }
class GetDetailsButton extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e, url) {
e.preventDefault();
if (this.props.data.fetching) {
return
}
this.props.updateEpisodeDetailsStore(this.props.data.show_imdb_id, this.props.data.season, this.props.data.episode);
this.props.getEpisodeDetails(this.props.data.show_imdb_id, this.props.data.season, this.props.data.episode);
}
render() {
return (
<span className="episode-button">
<a type="button" className="btn btn-xs btn-info" onClick={(e) => this.handleClick(e)}>
{this.props.data.fetching ||
<span>
<i className="fa fa-refresh"></i> Refresh
</span>
}
{this.props.data.fetching &&
<span>
<i className="fa fa-spin fa-refresh"></i> Refreshing
</span>
}
</a>
</span>
);
}
}

View File

@ -58,6 +58,8 @@ export default class ShowList extends React.Component {
show={selectedShow} show={selectedShow}
deleteFromWishlist={this.props.deleteShowFromWishlist} deleteFromWishlist={this.props.deleteShowFromWishlist}
addToWishlist={this.props.addShowToWishlist} addToWishlist={this.props.addShowToWishlist}
getDetails={this.props.getShowDetails}
fetching={this.props.showStore.getDetails}
/> />
</ListDetails> </ListDetails>
} }

View File

@ -3,7 +3,7 @@ import React from 'react'
import { Link } from 'react-router' import { Link } from 'react-router'
import { DropdownButton } from 'react-bootstrap' import { DropdownButton } from 'react-bootstrap'
import { WishlistButton } from '../buttons/actions' import { WishlistButton, RefreshButton } from '../buttons/actions'
export default function ShowButtons(props) { export default function ShowButtons(props) {
const imdbLink = `http://www.imdb.com/title/${props.show.imdb_id}`; const imdbLink = `http://www.imdb.com/title/${props.show.imdb_id}`;
@ -13,6 +13,8 @@ export default function ShowButtons(props) {
show={props.show} show={props.show}
addToWishlist={props.addToWishlist} addToWishlist={props.addToWishlist}
deleteFromWishlist={props.deleteFromWishlist} deleteFromWishlist={props.deleteFromWishlist}
getDetails={props.getDetails}
fetching={props.fetching}
/> />
<a type="button" className="btn btn-warning btn-sm" href={imdbLink}> <a type="button" className="btn btn-warning btn-sm" href={imdbLink}>
<i className="fa fa-external-link"></i> IMDB <i className="fa fa-external-link"></i> IMDB
@ -28,6 +30,11 @@ function ActionsButton(props) {
let wishlisted = (props.show.tracked_season !== null && props.show.tracked_episode !== null); let wishlisted = (props.show.tracked_season !== null && props.show.tracked_episode !== null);
return ( return (
<DropdownButton className="btn btn-default btn-sm" title="Actions" id="actions-button" dropup> <DropdownButton className="btn btn-default btn-sm" title="Actions" id="actions-button" dropup>
<RefreshButton
fetching={props.fetching}
resourceId={props.show.imdb_id}
getDetails={props.getDetails}
/>
<WishlistButton <WishlistButton
resourceId={props.show.imdb_id} resourceId={props.show.imdb_id}
wishlisted={wishlisted} wishlisted={wishlisted}

View File

@ -8,6 +8,7 @@ const defaultState = {
seasons: [], seasons: [],
}, },
search: "", search: "",
getDetails: false,
}; };
export default function showStore(state = defaultState, action) { export default function showStore(state = defaultState, action) {
@ -27,6 +28,15 @@ export default function showStore(state = defaultState, action) {
selectedImdbId: selectedImdbId, selectedImdbId: selectedImdbId,
loading: false, loading: false,
}) })
case 'SHOW_GET_DETAILS_PENDING':
return Object.assign({}, state, {
getDetails: true,
})
case 'SHOW_GET_DETAILS_FULFILLED':
return Object.assign({}, state, {
shows: updateShowDetails(state.shows.slice(), action.payload.data),
getDetails: false,
})
case 'SHOW_FETCH_DETAILS_PENDING': case 'SHOW_FETCH_DETAILS_PENDING':
return Object.assign({}, state, { return Object.assign({}, state, {
loading: true, loading: true,
@ -36,6 +46,14 @@ export default function showStore(state = defaultState, action) {
show: sortEpisodes(action.payload.data), show: sortEpisodes(action.payload.data),
loading: false, loading: false,
}) })
case 'EPISODE_GET_DETAILS':
return Object.assign({}, state, {
show: updateEpisode(Object.assign({}, state.show), true, action.payload),
})
case 'EPISODE_GET_DETAILS_FULFILLED':
return Object.assign({}, state, {
show: updateEpisode(Object.assign({}, state.show), false, action.payload.data),
})
case 'SEARCH_SHOWS_PENDING': case 'SEARCH_SHOWS_PENDING':
return Object.assign({}, state, { return Object.assign({}, state, {
loading: true, loading: true,
@ -64,6 +82,26 @@ export default function showStore(state = defaultState, action) {
} }
} }
function updateEpisode(show, fetching, data = null) {
// Error handling for PouuleT
if (data === null) {
for (let seasonIndex of Object.keys(show.seasons)) {
for (let episodeIndex of Object.keys(show.seasons[seasonIndex].episodes)) {
show.seasons[seasonIndex].episodes[episodeIndex].fetching = false;
}
}
return show
}
let seasonIndex = show.seasons.map((el) => el.season).indexOf(data.season.toString());
let episodeIndex = show.seasons[seasonIndex].episodes.map((el) => el.episode).indexOf(data.episode);
if ('id' in data) {
show.seasons[seasonIndex].episodes[episodeIndex] = data;
}
show.seasons[seasonIndex].episodes[episodeIndex].fetching = fetching;
return show
}
function sortEpisodes(show) { function sortEpisodes(show) {
let episodes = show.episodes; let episodes = show.episodes;
delete show["episodes"]; delete show["episodes"];
@ -75,6 +113,7 @@ function sortEpisodes(show) {
// Extract the seasons // Extract the seasons
let seasons = {}; let seasons = {};
for (let ep of episodes) { for (let ep of episodes) {
ep.fetching = false;
if (!seasons[ep.season]) { if (!seasons[ep.season]) {
seasons[ep.season] = { episodes: [] }; seasons[ep.season] = { episodes: [] };
} }
@ -149,3 +188,9 @@ function updateShowStoreWishlist(show, payload) {
show.tracked_episode = episode; show.tracked_episode = episode;
return show return show
} }
function updateShowDetails(shows, data) {
let index = shows.map((el) => el.imdb_id).indexOf(data.imdb_id);
shows[index] = data;
return shows
}