Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-1230] -> Input Caching in typesense search (#94) #95

Merged
merged 1 commit into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions scripts/indexr.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,24 @@ const pageQuery = `
fields {
slug
}
excerpt(pruneLength: 6700)
excerpt(pruneLength: 100)
}
}
}
}
`;

function pageToTypesenseRecord({ node }) {
const { id, frontmatter, ...rest } = node;
console.log('node', node);
const { id, frontmatter, fields = {}, headings = [], ...rest } = node;

const formattedHeadings = headings.map(h => h.value || '').filter(Boolean);
return {
objectID: id,
...frontmatter,
title: frontmatter.title || '',
search_keyword: String(frontmatter.search_keyword || ''),
slug: fields.slug || '',
excerpt: frontmatter.excerpt || '',
headings: formattedHeadings,
...rest,
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/SearchHits.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export const CustomSearchBox = connectSearchBox(SearchBox);
/* eslint-disable react/no-danger */
const Hits = ({ hits }) => (
<ul className="style">
{hits.length < 1 ? <li>No search results found</li> : ''}
{hits.length < 1 ? <li className='px-5 py-3 rounded-lg text-center'>No search results found</li> : ''}
{hits.map((hit) => (
<li key={hit.title}>
<a href={hit.fields.slug}>
<a href={hit?.slug}>
<span className="search-title" dangerouslySetInnerHTML={{ __html: hit._highlightResult.title.value }} />
<p dangerouslySetInnerHTML={{ __html: hit._snippetResult.excerpt.value }} />
</a>
Expand Down
9 changes: 8 additions & 1 deletion src/components/SearchHits.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,26 @@ ais-highlight-0000000000 {

.style {
list-style: none;
padding-top: 20px;
padding-top: 14px;
a {
color: #757575;
}
a:hover {
color: #fe6c37;
text-decoration: none;
}
p {
margin: 6px 0;
font-size: 14px;
line-height: 20px;
overflow-wrap: break-word;
}
}

.search-title {
font-weight: 700;
color: #0E5AD9;
font-size: 16px;
}

.ais-SearchBox-form {
Expand Down
57 changes: 39 additions & 18 deletions src/components/SearchInputBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@ import { SearchHits } from './SearchHits';

import TypesenseInstantsearchAdapter from "typesense-instantsearch-adapter";

// window.$ = $;

/* Algolia Search Bar */
const ClickOutHandler = require('react-onclickout');

// Create the Typesense InstantSearch Adapter instance

// @ts-ignore
console.log(process.env.TYPESENSE_SEARCH_API_KEY);
console.log(process.env.TYPESENSE_HOST);
// console.log(process.env.TYPESENSE_SEARCH_API_KEY);
// console.log(process.env.TYPESENSE_HOST);
const typesenseInstantsearchAdapter = new TypesenseInstantsearchAdapter({
server: {
apiKey: process.env.TYPESENSE_SEARCH_API_KEY, // Use your Typesense search-only API key here
Expand All @@ -43,6 +40,16 @@ const typesenseInstantsearchAdapter = new TypesenseInstantsearchAdapter({

export const searchClient = typesenseInstantsearchAdapter.searchClient;

const debounce = (func, delay) => {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
};

class SearchInputBox extends React.Component {
constructor(props) {
super(props);
Expand All @@ -52,29 +59,47 @@ class SearchInputBox extends React.Component {
cookie: '',
hasInput: false,
refresh: false,
searchQuery: ''
};

this.debouncedSearch = debounce(this.handleSearch, 300);
}

// Algolia - clicking out exits searchbox
onClickOut = (event) => {
const searchInput = document.getElementsByClassName(
'ais-SearchBox-input',
)[0].value;
const domNode = ReactDOM.findDOMNode(this);
if (searchInput === '' || !domNode || !domNode.contains(event.target))
this.setState({ hasInput: false });
} // end onClickOut
}

handleKeyUp = (event) => {
const query = event.currentTarget.value;
this.setState({
hasInput: query.length > 2,
});

this.setState({ searchQuery: '' }, () => {
this.debouncedSearch(query);
});
}

handleSearch = (query) => {
console.log('Searching for:', query);
this.setState({
refresh: !this.state.refresh,
searchQuery: query
});
}

/* eslint-enabe class-methods-use-this */

render() {
const {
refresh, hasInput
refresh, hasInput, searchQuery
} = this.state;
return (
<>

<div className={!hasInput ? 'form-inline flex w-1/5 items-center pl-4' : 'form-inline flex w-1/5 items-center pl-4 float-searchBox'}>
<label htmlFor="search-lc" />

Expand All @@ -84,7 +109,7 @@ class SearchInputBox extends React.Component {
indexName={process.env.TYPESENSE_COLLECTION}
refresh={refresh}
>
<Configure hitsPerPage={5} />
<Configure hitsPerPage={10} />

{/* forcefeed className because component does not accept natively as prop */}
<div className="search-icon">
Expand All @@ -107,23 +132,19 @@ class SearchInputBox extends React.Component {
translations={{
placeholder: 'Search',
}}
onKeyUp={(event) => {
this.setState({
hasInput: event.currentTarget.value.length > 2,
});
}}
onKeyUp={this.handleKeyUp}
/>

<div className={!hasInput ? 'input-empty' : '-mt-1.5 absolute background-white bg-white search_results border h-full top-20 w-2/8'}>
<div className="container">
<div className="row">
<div className="col-12">
<SearchHits hitComponent={Hits} />
{searchQuery && <SearchHits hitComponent={Hits} />}
</div>
</div>
<div className="row">
<div className="col-12">
<Pagination />
{searchQuery && <Pagination />}
</div>
</div>
</div>
Expand Down
18 changes: 14 additions & 4 deletions src/templates/page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -486,17 +486,21 @@ code[class*="language-"] {

.float-searchBox {
position: fixed;
top: 0;
right: 0;
top: 30px;
right: 30px;
z-index: 3;
padding: 1.6rem 1rem;
width: 24.1%;
height: 100%;
max-height: 94vh;
display: block;
border-left: 1px solid rgba(229, 231, 235, var(--tw-border-opacity));
background-color: #fff;
border-radius: 8px;
backdrop-filter: blur(26px);
padding: 0.9rem 1rem;
transition: all 0.25s ease-in;
@media (max-width: 576px) {
width: 85%;
height: 90vh !important;
}
.ais-SearchBox,
.search-icon {
Expand All @@ -519,6 +523,7 @@ code[class*="language-"] {
border-left: 0;
background-color: #f5f5f5;
overflow-y: auto;
border-radius: 8px;
.ais-Pagination-list {
display: flex;
padding: 0.25rem 0 0.5rem;
Expand All @@ -531,6 +536,11 @@ code[class*="language-"] {
}
}
}
.ais-SearchBox-input{
font-size: 18px;
border-radius: 5px;
padding: .5rem 1rem;
}
}

.ais-SearchBox-input{
Expand Down
Loading