-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Basic search and select gif from Giphy
- Loading branch information
Showing
5 changed files
with
229 additions
and
23 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,5 +15,8 @@ | |
}, | ||
"devDependencies": { | ||
"@wordpress/scripts": "^7.1.2" | ||
}, | ||
"dependencies": { | ||
"react-photo-gallery": "^8.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { Component, Fragment } from '@wordpress/element'; | ||
import { TextControl, Spinner } from '@wordpress/components'; | ||
import Gallery from "react-photo-gallery"; | ||
|
||
export default class SearchGiphy extends Component { | ||
constructor(props) { | ||
super(props); | ||
} | ||
|
||
render() { | ||
const { | ||
search, | ||
onSearchChangeHandler, | ||
isLoading, | ||
gifs, | ||
onGiphyClick, | ||
pagination | ||
} = this.props; | ||
|
||
let result_gifs; | ||
if ( gifs[ pagination ] ) { | ||
result_gifs = []; | ||
result_gifs = gifs[ pagination ].map( ( gif_data ) => { | ||
return { | ||
src: gif_data.images.downsized_medium.url, | ||
width: gif_data.images.downsized_medium.width, | ||
height: gif_data.images.downsized_medium.height, | ||
}; | ||
} ) | ||
} | ||
|
||
return ( | ||
<Fragment> | ||
<TextControl | ||
label="Search GIF" | ||
value={ search } | ||
onChange={ ( search ) => { | ||
onSearchChangeHandler( search ); | ||
} } | ||
/> | ||
|
||
{ isLoading && ( | ||
<Spinner /> | ||
) } | ||
|
||
{ result_gifs && result_gifs.length && ( | ||
<Fragment> | ||
<Gallery photos={ result_gifs } onClick={ onGiphyClick } /> | ||
</Fragment> | ||
) } | ||
|
||
{ result_gifs && result_gifs.length === 0 && ( | ||
<p>{ `Nothing found for '${search}'.` }</p> | ||
) } | ||
|
||
</Fragment> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,146 @@ | ||
import { Component } from '@wordpress/element'; | ||
import { TextControl } from '@wordpress/components'; | ||
import { AlignmentToolbar, BlockControls, BlockAlignmentToolbar } from '@wordpress/editor'; | ||
import { addQueryArgs } from '@wordpress/url'; | ||
import { debounce } from 'lodash'; | ||
|
||
import SearchGiphy from "./components/SearchGiphy"; | ||
|
||
export default class Edit extends Component { | ||
constructor( props ) { | ||
super( props ); | ||
|
||
this.state = { | ||
isLoading: false, // If currently fetching from Giphy. | ||
isSearching: !props.attributes.gif, // If we need to show the search field. | ||
gifs: [], // Cache results from Giphy. | ||
pagination: 0, // Current pagination. | ||
}; | ||
|
||
// Get the API Key from https://developers.giphy.com/. | ||
this.API_KEY = '[INSERT YOUR API KEY HERE]'; | ||
this.GIPHY_ENDPOINT = 'https://api.giphy.com/v1/gifs/search'; | ||
this.GIPHY_RESULTS_LIMIT = 5; | ||
|
||
this.onSearchChangeHandler = this.onSearchChangeHandler.bind( this ); | ||
this.fetchGiphy = this.fetchGiphy.bind( this ); | ||
// Use debounce to prevent multiple concurrent request to Giphy. | ||
this.onSearchChange = debounce( this.onSearchChange.bind( this ), 500 ); | ||
this.onGiphyClick = this.onGiphyClick.bind( this ); | ||
} | ||
|
||
componentWillUnmount() { | ||
this.onSearchChange.cancel(); | ||
} | ||
|
||
/** | ||
* Debounced function | ||
* | ||
* @returns {Promise<void>} | ||
*/ | ||
async onSearchChange() { | ||
const { | ||
attributes: { search } | ||
} = this.props; | ||
|
||
const pagination = this.state.pagination / this.GIPHY_RESULTS_LIMIT; | ||
|
||
const results = await this.fetchGiphy( search, pagination ); | ||
|
||
if ( 200 !== results.meta.status ) { | ||
// TODO handle error. | ||
return; | ||
} | ||
|
||
// The idea is to 'cache' the past results in the state. | ||
// Something like | ||
// gifs[0] => Will contain results of pagination 0. | ||
// gifs[1] => Results of pagination 1. | ||
// and so on.. | ||
let gifs = this.state.gifs; | ||
gifs[ pagination ] = results.data; | ||
|
||
this.setState( { | ||
isLoading: false, | ||
pagination: pagination, | ||
gifs: gifs | ||
} ); | ||
} | ||
|
||
/** | ||
* Fetch data from Giphy. | ||
* | ||
* @param search string | ||
* @param pagination int | ||
* | ||
* @returns {Promise<any>} | ||
*/ | ||
fetchGiphy( search, pagination ) { | ||
// Build the request url. | ||
const requestUrl = addQueryArgs( this.GIPHY_ENDPOINT, { | ||
q: search, | ||
limit: this.GIPHY_RESULTS_LIMIT, | ||
api_key: this.API_KEY, | ||
offset: pagination, | ||
} ); | ||
|
||
return fetch( requestUrl ) | ||
.then( data => data.json() ) | ||
.catch( error => error ); | ||
}; | ||
|
||
onGiphyClick( event, { photo } ) { | ||
// Save the selected photo data as `gif` in the DB. | ||
this.props.setAttributes( { gif: photo } ); | ||
this.setState( { isSearching: false } ); | ||
} | ||
|
||
onSearchChangeHandler( search ) { | ||
this.setState( { isLoading: true } ); | ||
// Save the search keyword as `search` in the DB. | ||
this.props.setAttributes( { search } ); | ||
this.onSearchChange(); | ||
} | ||
|
||
render() { | ||
const { | ||
attributes: { | ||
search | ||
search, | ||
gif, | ||
blockAlignment, | ||
textAlignment | ||
}, | ||
setAttributes, | ||
className, | ||
setAttributes | ||
} = this.props; | ||
|
||
const { isLoading, isSearching, gifs, pagination } = this.state; | ||
|
||
return ( | ||
<TextControl | ||
label="Search GIF" | ||
value={ search } | ||
onChange={ search => setAttributes( { search } )} | ||
/> | ||
<div className={ className }> | ||
<BlockControls> | ||
<BlockAlignmentToolbar | ||
value={ blockAlignment } | ||
onChange={ blockAlignment => setAttributes( { blockAlignment } ) } | ||
/> | ||
<AlignmentToolbar | ||
value={ textAlignment } | ||
onChange={ textAlignment => setAttributes( { textAlignment } ) } | ||
/> | ||
</BlockControls> | ||
|
||
{ isSearching ? ( | ||
<SearchGiphy | ||
search={ search } | ||
onSearchChangeHandler={ this.onSearchChangeHandler } | ||
isLoading={ isLoading } | ||
gifs={ gifs } | ||
onGiphyClick={ this.onGiphyClick } | ||
pagination={ pagination } | ||
/> | ||
) : ( | ||
<img src={ gif.src } /> | ||
) } | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters