Skip to content

Commit f47bba8

Browse files
Merge pull request #95 from testsigmahq/dev
[WEB-1230] -> Input Caching in typesense search (#94)
2 parents 040d60c + 5978706 commit f47bba8

5 files changed

Lines changed: 72 additions & 29 deletions

File tree

scripts/indexr.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,24 @@ const pageQuery = `
2929
fields {
3030
slug
3131
}
32-
excerpt(pruneLength: 6700)
32+
excerpt(pruneLength: 100)
3333
}
3434
}
3535
}
3636
}
3737
`;
3838

3939
function pageToTypesenseRecord({ node }) {
40-
const { id, frontmatter, ...rest } = node;
41-
console.log('node', node);
40+
const { id, frontmatter, fields = {}, headings = [], ...rest } = node;
41+
42+
const formattedHeadings = headings.map(h => h.value || '').filter(Boolean);
4243
return {
4344
objectID: id,
44-
...frontmatter,
45+
title: frontmatter.title || '',
46+
search_keyword: String(frontmatter.search_keyword || ''),
47+
slug: fields.slug || '',
48+
excerpt: frontmatter.excerpt || '',
49+
headings: formattedHeadings,
4550
...rest,
4651
};
4752
}

src/components/SearchHits.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ export const CustomSearchBox = connectSearchBox(SearchBox);
2222
/* eslint-disable react/no-danger */
2323
const Hits = ({ hits }) => (
2424
<ul className="style">
25-
{hits.length < 1 ? <li>No search results found</li> : ''}
25+
{hits.length < 1 ? <li className='px-5 py-3 rounded-lg text-center'>No search results found</li> : ''}
2626
{hits.map((hit) => (
2727
<li key={hit.title}>
28-
<a href={hit.fields.slug}>
28+
<a href={hit?.slug}>
2929
<span className="search-title" dangerouslySetInnerHTML={{ __html: hit._highlightResult.title.value }} />
3030
<p dangerouslySetInnerHTML={{ __html: hit._snippetResult.excerpt.value }} />
3131
</a>

src/components/SearchHits.scss

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,26 @@ ais-highlight-0000000000 {
1919

2020
.style {
2121
list-style: none;
22-
padding-top: 20px;
22+
padding-top: 14px;
2323
a {
2424
color: #757575;
2525
}
2626
a:hover {
2727
color: #fe6c37;
2828
text-decoration: none;
2929
}
30+
p {
31+
margin: 6px 0;
32+
font-size: 14px;
33+
line-height: 20px;
34+
overflow-wrap: break-word;
35+
}
3036
}
3137

3238
.search-title {
3339
font-weight: 700;
3440
color: #0E5AD9;
41+
font-size: 16px;
3542
}
3643

3744
.ais-SearchBox-form {

src/components/SearchInputBox.jsx

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,13 @@ import { SearchHits } from './SearchHits';
1313

1414
import TypesenseInstantsearchAdapter from "typesense-instantsearch-adapter";
1515

16-
// window.$ = $;
17-
18-
/* Algolia Search Bar */
1916
const ClickOutHandler = require('react-onclickout');
2017

2118
// Create the Typesense InstantSearch Adapter instance
2219

2320
// @ts-ignore
24-
console.log(process.env.TYPESENSE_SEARCH_API_KEY);
25-
console.log(process.env.TYPESENSE_HOST);
21+
// console.log(process.env.TYPESENSE_SEARCH_API_KEY);
22+
// console.log(process.env.TYPESENSE_HOST);
2623
const typesenseInstantsearchAdapter = new TypesenseInstantsearchAdapter({
2724
server: {
2825
apiKey: process.env.TYPESENSE_SEARCH_API_KEY, // Use your Typesense search-only API key here
@@ -43,6 +40,16 @@ const typesenseInstantsearchAdapter = new TypesenseInstantsearchAdapter({
4340

4441
export const searchClient = typesenseInstantsearchAdapter.searchClient;
4542

43+
const debounce = (func, delay) => {
44+
let timer;
45+
return function (...args) {
46+
clearTimeout(timer);
47+
timer = setTimeout(() => {
48+
func.apply(this, args);
49+
}, delay);
50+
};
51+
};
52+
4653
class SearchInputBox extends React.Component {
4754
constructor(props) {
4855
super(props);
@@ -52,29 +59,47 @@ class SearchInputBox extends React.Component {
5259
cookie: '',
5360
hasInput: false,
5461
refresh: false,
62+
searchQuery: ''
5563
};
64+
65+
this.debouncedSearch = debounce(this.handleSearch, 300);
5666
}
5767

58-
// Algolia - clicking out exits searchbox
5968
onClickOut = (event) => {
6069
const searchInput = document.getElementsByClassName(
6170
'ais-SearchBox-input',
6271
)[0].value;
6372
const domNode = ReactDOM.findDOMNode(this);
6473
if (searchInput === '' || !domNode || !domNode.contains(event.target))
6574
this.setState({ hasInput: false });
66-
} // end onClickOut
75+
}
6776

77+
handleKeyUp = (event) => {
78+
const query = event.currentTarget.value;
79+
this.setState({
80+
hasInput: query.length > 2,
81+
});
82+
83+
this.setState({ searchQuery: '' }, () => {
84+
this.debouncedSearch(query);
85+
});
86+
}
87+
88+
handleSearch = (query) => {
89+
console.log('Searching for:', query);
90+
this.setState({
91+
refresh: !this.state.refresh,
92+
searchQuery: query
93+
});
94+
}
6895

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

7197
render() {
7298
const {
73-
refresh, hasInput
99+
refresh, hasInput, searchQuery
74100
} = this.state;
75101
return (
76102
<>
77-
78103
<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'}>
79104
<label htmlFor="search-lc" />
80105

@@ -84,7 +109,7 @@ class SearchInputBox extends React.Component {
84109
indexName={process.env.TYPESENSE_COLLECTION}
85110
refresh={refresh}
86111
>
87-
<Configure hitsPerPage={5} />
112+
<Configure hitsPerPage={10} />
88113

89114
{/* forcefeed className because component does not accept natively as prop */}
90115
<div className="search-icon">
@@ -107,23 +132,19 @@ class SearchInputBox extends React.Component {
107132
translations={{
108133
placeholder: 'Search',
109134
}}
110-
onKeyUp={(event) => {
111-
this.setState({
112-
hasInput: event.currentTarget.value.length > 2,
113-
});
114-
}}
135+
onKeyUp={this.handleKeyUp}
115136
/>
116137

117138
<div className={!hasInput ? 'input-empty' : '-mt-1.5 absolute background-white bg-white search_results border h-full top-20 w-2/8'}>
118139
<div className="container">
119140
<div className="row">
120141
<div className="col-12">
121-
<SearchHits hitComponent={Hits} />
142+
{searchQuery && <SearchHits hitComponent={Hits} />}
122143
</div>
123144
</div>
124145
<div className="row">
125146
<div className="col-12">
126-
<Pagination />
147+
{searchQuery && <Pagination />}
127148
</div>
128149
</div>
129150
</div>

src/templates/page.scss

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -486,17 +486,21 @@ code[class*="language-"] {
486486

487487
.float-searchBox {
488488
position: fixed;
489-
top: 0;
490-
right: 0;
489+
top: 30px;
490+
right: 30px;
491491
z-index: 3;
492492
padding: 1.6rem 1rem;
493493
width: 24.1%;
494-
height: 100%;
494+
max-height: 94vh;
495495
display: block;
496496
border-left: 1px solid rgba(229, 231, 235, var(--tw-border-opacity));
497-
background-color: #fff;
497+
border-radius: 8px;
498+
backdrop-filter: blur(26px);
499+
padding: 0.9rem 1rem;
500+
transition: all 0.25s ease-in;
498501
@media (max-width: 576px) {
499502
width: 85%;
503+
height: 90vh !important;
500504
}
501505
.ais-SearchBox,
502506
.search-icon {
@@ -519,6 +523,7 @@ code[class*="language-"] {
519523
border-left: 0;
520524
background-color: #f5f5f5;
521525
overflow-y: auto;
526+
border-radius: 8px;
522527
.ais-Pagination-list {
523528
display: flex;
524529
padding: 0.25rem 0 0.5rem;
@@ -531,6 +536,11 @@ code[class*="language-"] {
531536
}
532537
}
533538
}
539+
.ais-SearchBox-input{
540+
font-size: 18px;
541+
border-radius: 5px;
542+
padding: .5rem 1rem;
543+
}
534544
}
535545

536546
.ais-SearchBox-input{

0 commit comments

Comments
 (0)