Add show search

This commit is contained in:
Grégoire Delattre 2017-01-06 22:01:33 +01:00
parent 74b2f351bd
commit df58a80125
7 changed files with 68 additions and 8 deletions

View File

@ -1,6 +1,7 @@
package shows package shows
import ( import (
"encoding/json"
"errors" "errors"
"net/http" "net/http"
@ -27,15 +28,21 @@ func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) err
// SearchShow will search a show // SearchShow will search a show
func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error { func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error {
key := r.FormValue("key") var data struct {
if key == "" { Key string `json:"key"`
}
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
return err
}
if data.Key == "" {
return env.RenderError(w, errors.New("no given key")) return env.RenderError(w, errors.New("no given key"))
} }
var shows []*polochon.Show var shows []*polochon.Show
searchers := env.Config.ShowSearchers searchers := env.Config.ShowSearchers
for _, searcher := range searchers { for _, searcher := range searchers {
result, err := searcher.SearchShow(key, env.Log) result, err := searcher.SearchShow(data.Key, env.Log)
if err != nil { if err != nil {
env.Log.Errorf("error while searching show : %s", err) env.Log.Errorf("error while searching show : %s", err)
continue continue
@ -43,7 +50,7 @@ func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error {
shows = append(shows, result...) shows = append(shows, result...)
} }
env.Log.Debugf("got %d shows doing search %q", len(shows), key) env.Log.Debugf("got %d shows doing search %q", len(shows), data.Key)
showList := []*Show{} showList := []*Show{}
for _, s := range shows { for _, s := range shows {
show := New(s.ImdbID) show := New(s.ImdbID)

View File

@ -86,7 +86,7 @@ func main() {
env.Handle("/shows/{id:tt[0-9]+}", shows.GetDetailsHandler) env.Handle("/shows/{id:tt[0-9]+}", shows.GetDetailsHandler)
env.Handle("/shows/refresh", extmedias.RefreshShows) env.Handle("/shows/refresh", extmedias.RefreshShows)
env.Handle("/shows/explore", extmedias.ExploreShows) env.Handle("/shows/explore", extmedias.ExploreShows)
env.Handle("/shows/search", shows.SearchShow) env.Handle("/shows/search", shows.SearchShow).Methods("POST")
n := negroni.Classic() n := negroni.Classic()
n.Use(authMiddleware) n.Use(authMiddleware)

View File

@ -112,6 +112,13 @@ export function fetchShows(url) {
) )
} }
export function searchShows(search) {
return request(
'SEARCH_SHOWS',
configureAxios().post('/shows/search', search)
)
}
export function fetchShowDetails(imdbId) { export function fetchShowDetails(imdbId) {
return request( return request(
'SHOW_FETCH_DETAILS', 'SHOW_FETCH_DETAILS',

View File

@ -90,10 +90,12 @@ const MovieListSearch = (props) => (
const ShowListPopular = (props) => ( const ShowListPopular = (props) => (
<ShowList {...props} showsUrl='/shows/explore'/> <ShowList {...props} showsUrl='/shows/explore'/>
) )
const ShowDetailsView = (props) => ( const ShowDetailsView = (props) => (
<ShowDetails {...props} /> <ShowDetails {...props} />
) )
const ShowListSearch = (props) => (
<ShowList {...props} />
)
ReactDOM.render(( ReactDOM.render((
<Provider store={store}> <Provider store={store}>
@ -106,6 +108,7 @@ ReactDOM.render((
<Route path="/movies/search/:search" component={UserIsAuthenticated(MovieListSearch)} /> <Route path="/movies/search/:search" component={UserIsAuthenticated(MovieListSearch)} />
<Route path="/movies/popular" component={UserIsAuthenticated(MovieListPopular)} /> <Route path="/movies/popular" component={UserIsAuthenticated(MovieListPopular)} />
<Route path="/movies/polochon(/:page)" component={UserIsAuthenticated(MovieListPolochon)} /> <Route path="/movies/polochon(/:page)" component={UserIsAuthenticated(MovieListPolochon)} />
<Route path="/shows/search/:search" component={UserIsAuthenticated(ShowListSearch)} />
<Route path="/shows/popular" component={UserIsAuthenticated(ShowListPopular)} /> <Route path="/shows/popular" component={UserIsAuthenticated(ShowListPopular)} />
<Route path="/shows/details/:imdbId" component={UserIsAuthenticated(ShowDetailsView)} /> <Route path="/shows/details/:imdbId" component={UserIsAuthenticated(ShowDetailsView)} />
</Route> </Route>

View File

@ -10,19 +10,28 @@ export default class NavBar extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleMovieSearch = this.handleMovieSearch.bind(this); this.handleMovieSearch = this.handleMovieSearch.bind(this);
this.handleShowSearch = this.handleShowSearch.bind(this);
} }
handleMovieSearch() { handleMovieSearch() {
this.props.router.push(`/movies/search/${encodeURI(this.props.movieStore.search)}`) this.props.router.push(`/movies/search/${encodeURI(this.props.movieStore.search)}`)
} }
handleShowSearch() {
this.props.router.push(`/shows/search/${encodeURI(this.props.showStore.search)}`)
}
render() { render() {
const username = this.props.userStore.username; const username = this.props.userStore.username;
const isLoggedIn = username !== "" ? true : false; const isLoggedIn = username !== "" ? true : false;
const location = this.props.router.getCurrentLocation().pathname; const location = this.props.router.getCurrentLocation().pathname;
let displayMovieSearch = false; let displayMovieSearch = false;
let displayShowSearch = false;
if (isLoggedIn && location.indexOf("movies") > -1) if (isLoggedIn && location.indexOf("movies") > -1)
{ {
displayMovieSearch = true; displayMovieSearch = true;
} }
if (isLoggedIn && location.indexOf("shows") > -1)
{
displayShowSearch = true;
}
return ( return (
<div> <div>
<Navbar fluid fixedTop collapseOnSelect> <Navbar fluid fixedTop collapseOnSelect>
@ -72,7 +81,19 @@ export default class NavBar extends React.Component {
<Control.text <Control.text
model="movieStore.search" model="movieStore.search"
className="form-control" className="form-control"
placeholder="Search" placeholder="Search movies"
updateOn="change"
/>
</Form>
</Navbar.Form>
}
{displayShowSearch &&
<Navbar.Form pullRight>
<Form model="showStore" className="input-group" onSubmit={() => this.handleShowSearch()}>
<Control.text
model="showStore.search"
className="form-control"
placeholder="Search shows"
updateOn="change" updateOn="change"
/> />
</Form> </Form>

View File

@ -20,7 +20,24 @@ function ShowButtons(props) {
export default class ShowList extends React.Component { export default class ShowList extends React.Component {
componentWillMount() { componentWillMount() {
if (this.props.showsUrl) {
this.props.fetchShows(this.props.showsUrl); this.props.fetchShows(this.props.showsUrl);
} else if (this.props.params && this.props.params.search != "") {
this.props.searchShows({
key: this.props.params.search
});
}
}
componentWillUpdate(nextProps, nextState) {
if (!nextProps.params || nextProps.params.search === "") {
return
}
if (this.props.params.search === nextProps.params.search) {
return
}
this.props.searchShows({
key: nextProps.params.search
});
} }
render() { render() {
const shows = this.props.showStore.shows; const shows = this.props.showStore.shows;

View File

@ -6,6 +6,7 @@ const defaultState = {
show: { show: {
seasons: [], seasons: [],
}, },
search: "",
}; };
export default function showStore(state = defaultState, action) { export default function showStore(state = defaultState, action) {
@ -25,6 +26,10 @@ export default function showStore(state = defaultState, action) {
show: sortEpisodes(action.payload.data), show: sortEpisodes(action.payload.data),
}) })
return state; return state;
case 'SEARCH_SHOWS_FULFILLED':
return Object.assign({}, state, {
shows: action.payload.data,
})
case 'SELECT_SHOW': case 'SELECT_SHOW':
// Don't select the show if we're fetching another show's details // Don't select the show if we're fetching another show's details
if (state.fetchingDetails) { if (state.fetchingDetails) {