Rewrote most of how api calls are made when searching for a movie and how the returning data is handled. We now have finer handling of status response from the original api call aswell as if any of the functions hit a error e.g. not hitting the server, than we have our own errors thrown. Also updated the page incrementers to updated the last api call with a higher or lower number.
This commit is contained in:
@@ -4,6 +4,7 @@ import MovieObject from './MovieObject.jsx';
|
|||||||
|
|
||||||
// StyleComponents
|
// StyleComponents
|
||||||
import searchStyle from './styles/searchRequestStyle.jsx';
|
import searchStyle from './styles/searchRequestStyle.jsx';
|
||||||
|
import movieStyle from './styles/movieObjectStyle.jsx'
|
||||||
|
|
||||||
import URI from 'urijs';
|
import URI from 'urijs';
|
||||||
|
|
||||||
@@ -13,23 +14,25 @@ class SearchRequest extends React.Component {
|
|||||||
super(props)
|
super(props)
|
||||||
// Constructor with states holding the search query and the element of reponse.
|
// Constructor with states holding the search query and the element of reponse.
|
||||||
this.state = {
|
this.state = {
|
||||||
|
lastApiCallURI: '',
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
responseMovieList: null,
|
responseMovieList: null,
|
||||||
movieFilter: true,
|
movieFilter: true,
|
||||||
showFilter: false,
|
showFilter: false,
|
||||||
discoverType: '',
|
discoverType: '',
|
||||||
page: 1
|
page: 1,
|
||||||
|
resultHeader: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
this.allowedDiscoverTypes = [
|
this.allowedListTypes = [
|
||||||
'discover', 'popular', 'nowplaying', 'upcoming'
|
'discover', 'popular', 'nowplaying', 'upcoming'
|
||||||
]
|
]
|
||||||
|
|
||||||
this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb';
|
this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb/';
|
||||||
// this.baseUrl = 'http://localhost:31459/api/v1/tmdb/';
|
// this.baseUrl = 'http://localhost:31459/api/v1/tmdb/';
|
||||||
|
|
||||||
this.URLs = {
|
this.URLs = {
|
||||||
request: 'https://apollo.kevinmidboe.com/api/v1/plex/request?page='+this.state.page+'&query=',
|
searchRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request',
|
||||||
// request: 'http://localhost:31459/api/v1/plex/request?page='+this.state.page+'&query=',
|
// request: 'http://localhost:31459/api/v1/plex/request?page='+this.state.page+'&query=',
|
||||||
upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming',
|
upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming',
|
||||||
// upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming',
|
// upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming',
|
||||||
@@ -45,26 +48,125 @@ class SearchRequest extends React.Component {
|
|||||||
this.fetchDiscover('upcoming');
|
this.fetchDiscover('upcoming');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles all errors of the response of a fetch call
|
// Handles all errors of the response of a fetch call
|
||||||
handleErrors(response) {
|
handleErrors(response) {
|
||||||
if (!response.ok) {
|
if (!response.ok)
|
||||||
throw Error(response.status);
|
throw Error(response.status);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
return response;
|
|
||||||
}
|
handleQueryError(response) {
|
||||||
|
if (!response.ok) {
|
||||||
|
if (response.status === 404) {
|
||||||
|
this.setState({
|
||||||
|
responseMovieList: <h1>Nothing found for search query: { this.findQueryInURI(uri) }</h1>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpacks the query value of a uri
|
||||||
|
findQueryValueInURI(uri) {
|
||||||
|
let uriSearchValues = uri.query(true);
|
||||||
|
let queryValue = uriSearchValues['query']
|
||||||
|
|
||||||
|
return queryValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPageNumber() {
|
||||||
|
this.state.page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test this by calling missing endpoint or 404 query and see what code
|
||||||
|
// and filter the error message based on the code.
|
||||||
|
// Calls a uri and returns the response as json
|
||||||
|
callURI(uri) {
|
||||||
|
return fetch(uri)
|
||||||
|
.then(response => { return response })
|
||||||
|
.catch(error => {
|
||||||
|
throw Error('Something went wrong while fetching URI.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Saves the input string as a h1 element in responseMovieList state
|
||||||
|
fillResponseMovieListWithError(msg) {
|
||||||
|
this.setState({
|
||||||
|
responseMovieList: <h1>{ msg }</h1>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we first call api for a search with the input uri, handle any errors
|
||||||
|
// and fill the reponseData from api into the state of reponseMovieList as movieObjects
|
||||||
|
callSearchFillMovieList(uri) {
|
||||||
|
Promise.resolve()
|
||||||
|
.then(() => this.callURI(uri))
|
||||||
|
.then(response => {
|
||||||
|
// If we get a error code for the request
|
||||||
|
if (!response.ok) {
|
||||||
|
if (response.status === 404) {
|
||||||
|
let errorMsg = 'Nothing found for the search query: ' + this.findQueryValueInURI(uri);
|
||||||
|
this.fillResponseMovieListWithError(errorMsg)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let errorMsg = 'Error fetching query from server ' + this.response.status;
|
||||||
|
this.fillResponseMovieListWithError(errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to json and update the state of responseMovieList with the results of the api call
|
||||||
|
// mapped as a movieObject.
|
||||||
|
response.json()
|
||||||
|
.then(responseData => {
|
||||||
|
this.setState({
|
||||||
|
responseMovieList: responseData.results.map(searchResultItem => this.createMovieObjects(searchResultItem)),
|
||||||
|
lastApiCallURI: uri // Save the value of the last sucessfull api call
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
throw Error('Something went wrong when fetching query.')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
searchSeasonedRequest() {
|
||||||
|
// Build uri with the url for searching requests
|
||||||
|
var uri = new URI(this.URLs.searchRequest);
|
||||||
|
// Add input of search query and page count to the uri payload
|
||||||
|
uri = uri.search({ 'query': this.state.searchQuery, 'page': this.state.page });
|
||||||
|
|
||||||
|
if (this.state.showFilter)
|
||||||
|
uri = uri.addSearch('type', 'show');
|
||||||
|
|
||||||
|
|
||||||
|
// Send uri to call and fill the response list with movie/show objects
|
||||||
|
this.callSearchFillMovieList(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fetchDiscover(queryDiscoverType) {
|
fetchDiscover(queryDiscoverType) {
|
||||||
if (this.allowedDiscoverTypes.indexOf(queryDiscoverType) === -1)
|
if (this.allowedListTypes.indexOf(queryDiscoverType) === -1)
|
||||||
throw Error('Invalid discover type: ' + queryDiscoverType);
|
throw Error('Invalid discover type: ' + queryDiscoverType);
|
||||||
|
|
||||||
|
// Captialize the first letter of and save the discoverQueryType to resultHeader state.
|
||||||
|
this.state.resultHeader = queryDiscoverType.toLowerCase().replace(/\b[a-z]/g, function(letter) {
|
||||||
|
return letter.toUpperCase();
|
||||||
|
});
|
||||||
|
|
||||||
var uri = new URI(this.baseUrl);
|
var uri = new URI(this.baseUrl);
|
||||||
uri.segment(queryDiscoverType)
|
uri.segment(queryDiscoverType)
|
||||||
uri = uri.setSearch('page', this.state.page);
|
uri = uri.setSearch('page', this.state.page);
|
||||||
if (this.state.showFilter)
|
if (this.state.showFilter)
|
||||||
uri = uri.addSearch('type', 'show');
|
uri = uri.addSearch('type', 'show');
|
||||||
|
|
||||||
console.log(uri)
|
|
||||||
|
this.state.lastApiCallURI = uri;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
responseMovieList: 'Loading...'
|
responseMovieList: 'Loading...'
|
||||||
@@ -96,11 +198,15 @@ class SearchRequest extends React.Component {
|
|||||||
|
|
||||||
|
|
||||||
fetchQuery() {
|
fetchQuery() {
|
||||||
let url = this.URLs.request + this.state.searchQuery
|
let url = this.URLs.request + this.state.searchQuery;
|
||||||
if (this.state.showFilter) {
|
if (this.state.showFilter) {
|
||||||
url = url + '&type=tv'
|
url = url + '&type=tv'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.state.apiQuery = url;
|
||||||
|
console.log(this.state.apiQuery.toString());
|
||||||
|
this.state.resultHeader = "Results for: " + this.state.searchQuery + "";
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
// Check if the response is ok
|
// Check if the response is ok
|
||||||
.then(response => this.handleErrors(response))
|
.then(response => this.handleErrors(response))
|
||||||
@@ -135,7 +241,10 @@ class SearchRequest extends React.Component {
|
|||||||
// For checking if the enter key was pressed in the search field.
|
// For checking if the enter key was pressed in the search field.
|
||||||
_handleQueryKeyPress(e) {
|
_handleQueryKeyPress(e) {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
this.fetchQuery();
|
// this.fetchQuery();
|
||||||
|
// Reset page number for a new search
|
||||||
|
this.resetPageNumber();
|
||||||
|
this.searchSeasonedRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,21 +270,39 @@ class SearchRequest extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pageBackwards() {
|
pageBackwards() {
|
||||||
if (this.state.page > 1) {
|
if (this.state.page > 1) {
|
||||||
console.log('backwards');
|
let pageNumber = this.state.page - 1;
|
||||||
this.state.page--;
|
let uri = this.state.lastApiCallURI;
|
||||||
this.getUpcoming();
|
|
||||||
}
|
// Augment the page number of the uri with a callback
|
||||||
console.log(this.state.page)
|
uri.search(function(data) {
|
||||||
}
|
data.page = pageNumber;
|
||||||
|
});
|
||||||
|
|
||||||
pageForwards() {
|
// Call the api with the new uri
|
||||||
this.state.page++;
|
this.callSearchFillMovieList(uri);
|
||||||
this.getUpcoming();
|
// Update state of our page number after the call is done
|
||||||
console.log('forwards');
|
this.state.page = pageNumber;
|
||||||
console.log(this.state.page)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO need to get total page number and save in a state to not overflow
|
||||||
|
pageForwards() {
|
||||||
|
// Wrap this in the check
|
||||||
|
let pageNumber = this.state.page + 1;
|
||||||
|
let uri = this.state.lastApiCallURI;
|
||||||
|
|
||||||
|
// Augment the page number of the uri with a callback
|
||||||
|
uri.search(function(data) {
|
||||||
|
data.page = pageNumber;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the api with the new uri
|
||||||
|
this.callSearchFillMovieList(uri);
|
||||||
|
// Update state of our page number after the call is done
|
||||||
|
this.state.page = pageNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
@@ -186,40 +313,44 @@ class SearchRequest extends React.Component {
|
|||||||
<button onClick={() => {this.fetchDiscover('nowplaying')}}>Nowplaying</button>
|
<button onClick={() => {this.fetchDiscover('nowplaying')}}>Nowplaying</button>
|
||||||
<button onClick={() => {this.fetchDiscover('upcoming')}}>Upcoming</button>
|
<button onClick={() => {this.fetchDiscover('upcoming')}}>Upcoming</button>
|
||||||
|
|
||||||
<div className='backgroundHeader' style={searchStyle.backgroundHeader}>
|
<div className='backgroundHeader' style={searchStyle.backgroundHeader}>
|
||||||
<div className='pageTitle' style={searchStyle.pageTitle}>
|
<div className='pageTitle' style={searchStyle.pageTitle}>
|
||||||
<span style={searchStyle.pageTitleSpan}>Request new movies or tv shows</span>
|
<span style={searchStyle.pageTitleSpan}>Request new movies or tv shows</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='box' style={searchStyle.box}>
|
<div className='box' style={searchStyle.box}>
|
||||||
<div style={searchStyle.container}>
|
<div style={searchStyle.container}>
|
||||||
<span style={searchStyle.searchIcon}><i className="fa fa-search"></i></span>
|
<span style={searchStyle.searchIcon}><i className="fa fa-search"></i></span>
|
||||||
|
|
||||||
<input style={searchStyle.searchBar} type="text" id="search" placeholder="Search for new content..."
|
<input style={searchStyle.searchBar} type="text" id="search" placeholder="Search for new content..."
|
||||||
onKeyPress={(event) => this._handleQueryKeyPress(event)}
|
onKeyPress={(event) => this._handleQueryKeyPress(event)}
|
||||||
onChange={event => this.updateQueryState(event)}
|
onChange={event => this.updateQueryState(event)}
|
||||||
value={this.state.searchQuery}/>
|
value={this.state.searchQuery}/>
|
||||||
|
|
||||||
<span style={searchStyle.searchFilter}
|
<span style={searchStyle.searchFilter}
|
||||||
className="search_category hvrUnderlineFromCenter"
|
className="search_category hvrUnderlineFromCenter"
|
||||||
onClick={() => {this.toggleFilter('movies')}}
|
onClick={() => {this.toggleFilter('movies')}}
|
||||||
id="category_active">Movies</span>
|
id="category_active">Movies</span>
|
||||||
<span style={searchStyle.searchFilter}
|
<span style={searchStyle.searchFilter}
|
||||||
className="search_category hvrUnderlineFromCenter"
|
className="search_category hvrUnderlineFromCenter"
|
||||||
onClick={() => {this.toggleFilter('shows')}}
|
onClick={() => {this.toggleFilter('shows')}}
|
||||||
id="category_inactive">TV Shows</span>
|
id="category_inactive">TV Shows</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id='requestMovieList' ref='requestMovieList' style={searchStyle.requestWrapper}>
|
<div id='requestMovieList' ref='requestMovieList' style={searchStyle.requestWrapper}>
|
||||||
{this.state.responseMovieList}
|
|
||||||
</div>
|
<h1 style={searchStyle.resultHeader}>{this.state.resultHeader}</h1>
|
||||||
<div>
|
|
||||||
<button onClick={() => {this.pageBackwards()}}>Back</button>
|
{this.state.responseMovieList}
|
||||||
<button onClick={() => {this.pageForwards()}}>Forward</button>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
<div style={searchStyle.pageNavigationBar}>
|
||||||
|
<button onClick={() => {this.pageBackwards()}} style={searchStyle.pageNavigationButton}>Back</button>
|
||||||
|
<button onClick={() => {this.pageForwards()}} style={searchStyle.pageNavigationButton}>Forward</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user