Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Docs/client search with js search (#11505)
* revised draft with the changes applied. Example rebased * Style edits Grammar / typo fixes and various small edits to align with tone of existing docs * linted example files * Run linting
- Loading branch information
1 parent
ab90f46
commit bab4eae
Showing
9 changed files
with
1,127 additions
and
3 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
## Adding client search using Js Search | ||
|
||
The code in this folder is the full implementation for the documentation on how to add client search with [js-search](https://github.com/bvaughn/js-search). | ||
|
||
A live version of this example is located [here](https://pedantic-clarke-873963.netlify.com/) | ||
The endpoint that uses Gatsby API is located [here](https://pedantic-clarke-873963.netlify.com/search) |
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,41 @@ | ||
const path = require(`path`) | ||
const axios = require(`axios`) | ||
|
||
exports.createPages = ({ actions }) => { | ||
const { createPage } = actions | ||
return new Promise((resolve, reject) => { | ||
axios | ||
.get(`https://bvaughn.github.io/js-search/books.json`) | ||
.then(result => { | ||
const { data } = result | ||
/** | ||
* creates a page dynamic page with the data recieved | ||
* injects the data recived into the context object alongside with some options | ||
* to configure js-search | ||
*/ | ||
createPage({ | ||
path: `/search`, | ||
component: path.resolve(`./src/templates/ClientSearchTemplate.js`), | ||
context: { | ||
bookData: { | ||
allBooks: data.books, | ||
options: { | ||
indexStrategy: `Prefix match`, | ||
searchSanitizer: `Lower Case`, | ||
TitleIndex: true, | ||
AuthorIndex: true, | ||
SearchByTerm: true, | ||
}, | ||
}, | ||
}, | ||
}) | ||
resolve() | ||
}) | ||
.catch(err => { | ||
console.log(`====================================`) | ||
console.log(`error creating Page:${err}`) | ||
console.log(`====================================`) | ||
reject(new Error(`error on page creation:\n${err}`)) | ||
}) | ||
}) | ||
} |
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,24 @@ | ||
{ | ||
"name": "js-search-example", | ||
"private": true, | ||
"description": "Gatsby example site to demonstrate client side search", | ||
"version": "0.1.0", | ||
"keywords": [ | ||
"Gatsby", "client side search", "js-search" | ||
], | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "gatsby build", | ||
"develop": "gatsby develop", | ||
"start": "npm run develop", | ||
"serve": "gatsby serve", | ||
"test": "echo \"Write tests! -> https://gatsby.app/unit-testing\"" | ||
}, | ||
"dependencies": { | ||
"axios": "^0.18.0", | ||
"gatsby": "^2.0.104", | ||
"js-search": "^1.4.2", | ||
"react": "^16.5.1", | ||
"react-dom": "^16.5.1" | ||
} | ||
} |
224 changes: 224 additions & 0 deletions
224
examples/using-js-search/src/components/ClientSearch.js
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,224 @@ | ||
import React, { Component } from "react" | ||
import * as JsSearch from "js-search" | ||
|
||
class ClientSearch extends Component { | ||
state = { | ||
isLoading: true, | ||
searchResults: [], | ||
search: null, | ||
isError: false, | ||
indexByTitle: false, | ||
indexByAuthor: false, | ||
termFrequency: true, | ||
removeStopWords: false, | ||
searchQuery: ``, | ||
selectedStrategy: ``, | ||
selectedSanitizer: ``, | ||
} | ||
|
||
static getDerivedStateFromProps(nextProps, prevState) { | ||
if (prevState.search === null) { | ||
const { engine } = nextProps | ||
return { | ||
indexByTitle: engine.TitleIndex, | ||
indexByAuthor: engine.AuthorIndex, | ||
termFrequency: engine.SearchByTerm, | ||
selectedSanitizer: engine.searchSanitizer, | ||
selectedStrategy: engine.indexStrategy, | ||
} | ||
} | ||
return null | ||
} | ||
async componentDidMount() { | ||
this.rebuildIndex() | ||
} | ||
|
||
rebuildIndex = () => { | ||
const { | ||
selectedStrategy, | ||
selectedSanitizer, | ||
removeStopWords, | ||
termFrequency, | ||
indexByTitle, | ||
indexByAuthor, | ||
} = this.state | ||
const { books } = this.props | ||
|
||
const dataToSearch = new JsSearch.Search(`isbn`) | ||
if (removeStopWords) { | ||
dataToSearch.tokenizer = new JsSearch.StopWordsTokenizer( | ||
dataToSearch.tokenizer | ||
) | ||
} | ||
if (selectedStrategy === `All`) { | ||
dataToSearch.indexStrategy = new JsSearch.AllSubstringsIndexStrategy() | ||
} | ||
if (selectedStrategy === `Exact match`) { | ||
dataToSearch.indexStrategy = new JsSearch.ExactWordIndexStrategy() | ||
} | ||
if (selectedStrategy === `Prefix match`) { | ||
dataToSearch.indexStrategy = new JsSearch.PrefixIndexStrategy() | ||
} | ||
/* eslint-disable */ | ||
selectedSanitizer === `Case Sensitive` | ||
? (dataToSearch.sanitizer = new JsSearch.CaseSensitiveSanitizer()) | ||
: (dataToSearch.sanitizer = new JsSearch.LowerCaseSanitizer()) | ||
|
||
termFrequency === true | ||
? (dataToSearch.searchIndex = new JsSearch.TfIdfSearchIndex(`isbn`)) | ||
: (dataToSearch.searchIndex = new JsSearch.UnorderedSearchIndex()) | ||
/* eslint-enable */ | ||
if (indexByTitle) { | ||
dataToSearch.addIndex(`title`) | ||
} | ||
if (indexByAuthor) { | ||
dataToSearch.addIndex(`author`) | ||
} | ||
dataToSearch.addDocuments(books) | ||
this.setState({ search: dataToSearch, isLoading: false }) | ||
} | ||
searchData = e => { | ||
const { search } = this.state | ||
const queryResult = search.search(e.target.value) | ||
this.setState({ searchQuery: e.target.value, searchResults: queryResult }) | ||
} | ||
handleSubmit = e => { | ||
e.preventDefault() | ||
} | ||
render() { | ||
const { isLoading, isError, searchResults, searchQuery } = this.state | ||
const { books } = this.props | ||
const queryResults = searchQuery === `` ? books : searchResults | ||
if (isLoading) { | ||
return ( | ||
<div> | ||
<h1 style={{ marginTop: `3em` }}>Getting the search all setup</h1> | ||
</div> | ||
) | ||
} | ||
if (isError) { | ||
return ( | ||
<div> | ||
<h1 style={{ marginTop: `3em`, textAlign: `center` }}>Ohh no!!!!!</h1> | ||
<h3 | ||
style={{ | ||
marginTop: `2em`, | ||
padding: `2em 0em`, | ||
textAlign: `center`, | ||
}} | ||
> | ||
Something really bad happened | ||
</h3> | ||
</div> | ||
) | ||
} | ||
return ( | ||
<div> | ||
<div style={{ margin: `0 auto` }}> | ||
<form onSubmit={this.handleSubmit}> | ||
<div style={{ margin: `0 auto` }}> | ||
<label htmlFor="Search" style={{ paddingRight: `10px` }}> | ||
Enter your search here | ||
</label> | ||
<input | ||
id="Search" | ||
value={searchQuery} | ||
onChange={this.searchData} | ||
placeholder="Enter your search here" | ||
style={{ margin: `0 auto`, width: `400px` }} | ||
/> | ||
</div> | ||
</form> | ||
<div> | ||
Number of items: | ||
{queryResults.length} | ||
<table | ||
style={{ | ||
width: `100%`, | ||
borderCollapse: `collapse`, | ||
borderRadius: `4px`, | ||
border: `1px solid #d3d3d3`, | ||
}} | ||
> | ||
<thead style={{ border: `1px solid #808080` }}> | ||
<tr> | ||
<th | ||
style={{ | ||
textAlign: `left`, | ||
padding: `5px`, | ||
fontSize: `14px`, | ||
fontWeight: 600, | ||
borderBottom: `2px solid #d3d3d3`, | ||
cursor: `pointer`, | ||
}} | ||
> | ||
Book ISBN | ||
</th> | ||
<th | ||
style={{ | ||
textAlign: `left`, | ||
padding: `5px`, | ||
fontSize: `14px`, | ||
fontWeight: 600, | ||
borderBottom: `2px solid #d3d3d3`, | ||
cursor: `pointer`, | ||
}} | ||
> | ||
Book Title | ||
</th> | ||
<th | ||
style={{ | ||
textAlign: `left`, | ||
padding: `5px`, | ||
fontSize: `14px`, | ||
fontWeight: 600, | ||
borderBottom: `2px solid #d3d3d3`, | ||
cursor: `pointer`, | ||
}} | ||
> | ||
Book Author | ||
</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{/* eslint-disable */} | ||
{queryResults.map(item => { | ||
return ( | ||
<tr key={`row_${item.isbn}`}> | ||
<td | ||
style={{ | ||
fontSize: `14px`, | ||
border: `1px solid #d3d3d3`, | ||
}} | ||
> | ||
{item.isbn} | ||
</td> | ||
<td | ||
style={{ | ||
fontSize: `14px`, | ||
border: `1px solid #d3d3d3`, | ||
}} | ||
> | ||
{item.title} | ||
</td> | ||
<td | ||
style={{ | ||
fontSize: `14px`, | ||
border: `1px solid #d3d3d3`, | ||
}} | ||
> | ||
{item.author} | ||
</td> | ||
</tr> | ||
) | ||
})} | ||
{/* eslint-enable */} | ||
</tbody> | ||
</table> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
} | ||
export default ClientSearch |
Oops, something went wrong.