Skip to content

Commit

Permalink
Merge branch 'next' into FX-1139-autocomplete-requests-not-batched-wh…
Browse files Browse the repository at this point in the history
…en-using-umd-via-script-tags
  • Loading branch information
Haroenv authored Feb 23, 2022
2 parents aee71d0 + aa7caa9 commit e011c0f
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 260 deletions.
24 changes: 11 additions & 13 deletions examples/vue-instantsearch/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
<template>
<div>
<header class="header">
<div class="header-wrapper wrapper">
<nav class="header-nav">
<a href="/">Home</a>
</nav>
<div id="autocomplete"></div>
</div>
</header>

<ais-instant-search
:search-client="searchClient"
:index-name="indexName"
:routing="routing"
:middlewares="middlewares"
>
<header class="header">
<div class="header-wrapper wrapper">
<nav class="header-nav">
<a href="/">Home</a>
</nav>
<Autocomplete />
</div>
</header>

<ais-configure
:attributes-to-snippet.camel="['name:7', 'description:15']"
:snippet-ellipsis-text.camel="''"
Expand All @@ -32,7 +31,6 @@
</ais-panel>
</div>
<div>
<ais-search-box><template></template></ais-search-box>
<ais-hits>
<template v-slot:item="{ item }">
<article class="hit">
Expand Down Expand Up @@ -62,11 +60,12 @@
import { history as historyRouter } from 'instantsearch.js/es/lib/routers';
import { singleIndex as singleIndexMapping } from 'instantsearch.js/es/lib/stateMappings';
import { autocompleteMiddleware } from './autocompleteMiddleware';
import Autocomplete from './Autocomplete.vue';
import { INSTANT_SEARCH_INDEX_NAME } from './constants';
import { searchClient } from './searchClient';
export default {
components: { Autocomplete },
data() {
return {
searchClient,
Expand All @@ -75,7 +74,6 @@ export default {
router: historyRouter(),
stateMapping: singleIndexMapping(INSTANT_SEARCH_INDEX_NAME),
},
middlewares: [autocompleteMiddleware],
};
},
};
Expand Down
255 changes: 255 additions & 0 deletions examples/vue-instantsearch/src/Autocomplete.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
<template>
<div ref="autocompleteContainer"></div>
</template>

<script lang="jsx">
import { Fragment, render } from 'vue';
import { createWidgetMixin } from 'vue-instantsearch/vue3/es';
import { connectSearchBox } from 'instantsearch.js/es/connectors';
import { autocomplete } from '@algolia/autocomplete-js';
import { createQuerySuggestionsPlugin } from '@algolia/autocomplete-plugin-query-suggestions';
import { createLocalStorageRecentSearchesPlugin } from '@algolia/autocomplete-plugin-recent-searches';
import '@algolia/autocomplete-theme-classic';
import { createElement } from './utils/createElement';
import {
INSTANT_SEARCH_INDEX_NAME,
INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE,
} from './constants';
import { searchClient } from './searchClient';
function debounce(fn, time) {
let timerId;
return function (...args) {
if (timerId) {
clearTimeout(timerId);
}
timerId = setTimeout(() => fn(...args), time);
};
}
export default {
mixins: [createWidgetMixin({ connector: connectSearchBox })],
mounted() {
const { instantSearchInstance } = this;
function getInstantSearchCurrentCategory() {
const indexRenderState =
instantSearchInstance.renderState[INSTANT_SEARCH_INDEX_NAME];
const refinedCategory = indexRenderState?.hierarchicalMenu?.[
INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE
]?.items?.find(({ isRefined }) => isRefined);
return refinedCategory?.value;
}
function setInstantSearchUiState({
query,
category,
resetCategory = false,
}) {
let hierarchicalMenu;
if (resetCategory) {
hierarchicalMenu = {
hierarchicalMenu: { [INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE]: [] },
};
} else if (!category) {
hierarchicalMenu = {};
} else {
hierarchicalMenu = {
hierarchicalMenu: {
[INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE]: [category],
},
};
}
instantSearchInstance.setUiState((uiState) => ({
...uiState,
[INSTANT_SEARCH_INDEX_NAME]: {
...uiState[INSTANT_SEARCH_INDEX_NAME],
page: 1,
query,
...hierarchicalMenu,
},
}));
}
const debouncedSetInstantSearchUiState = debounce(
setInstantSearchUiState,
500
);
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
key: 'instantsearch',
limit: 3,
transformSource({ source }) {
return {
...source,
onSelect({ item }) {
setInstantSearchUiState({
query: item.label,
category: item.category,
});
},
};
},
});
const querySuggestionPluginInCategory = createQuerySuggestionsPlugin({
searchClient,
indexName: 'instant_search_demo_query_suggestions',
getSearchParams() {
const currentCategory = getInstantSearchCurrentCategory();
return recentSearchesPlugin.data.getAlgoliaSearchParams({
hitsPerPage: 3,
facetFilters: [
`${INSTANT_SEARCH_INDEX_NAME}.facets.exact_matches.categories.value:${currentCategory}`,
],
});
},
transformSource({ source }) {
const currentCategory = getInstantSearchCurrentCategory();
return {
...source,
sourceId: 'querySuggestionsPluginInCategory',
onSelect({ item }) {
setInstantSearchUiState({
query: item.query,
category: currentCategory,
});
},
getItems(params) {
if (!currentCategory) {
return [];
}
return source.getItems(params);
},
templates: {
...source.templates,
header({ items }) {
if (items.length === 0) {
return null;
}
return (
<Fragment>
<span className="aa-SourceHeaderTitle">
In {currentCategory}
</span>
<span className="aa-SourceHeaderLine"></span>
</Fragment>
);
},
},
};
},
});
const querySuggestionsPlugin = createQuerySuggestionsPlugin({
searchClient,
indexName: 'instant_search_demo_query_suggestions',
getSearchParams() {
const currentCategory = getInstantSearchCurrentCategory();
if (!currentCategory) {
return recentSearchesPlugin.data.getAlgoliaSearchParams({
hitsPerPage: 6,
});
}
return recentSearchesPlugin.data.getAlgoliaSearchParams({
hitsPerPage: 3,
facetFilters: [
`${INSTANT_SEARCH_INDEX_NAME}.facets.exact_matches.categories.value:-${currentCategory}`,
],
});
},
categoryAttribute: [
'instant_search',
'facets',
'exact_matches',
INSTANT_SEARCH_HIERARCHICAL_ATTRIBUTE,
],
transformSource({ source }) {
const currentCategory = getInstantSearchCurrentCategory();
return {
...source,
sourceId: 'querySuggestionsPlugin',
onSelect({ item }) {
setInstantSearchUiState({
query: item.query,
category: item.__autocomplete_qsCategory,
});
},
getItems(params) {
if (!params.state.query) {
return [];
}
return source.getItems(params);
},
templates: {
...source.templates,
header({ items }) {
if (!currentCategory || items.length === 0) {
return null;
}
return (
<Fragment>
<span className="aa-SourceHeaderTitle">
In other categories
</span>
<span className="aa-SourceHeaderLine" />
</Fragment>
);
},
},
};
},
});
const initialState =
instantSearchInstance.mainIndex.getHelper()?.state || {};
this.autocompleteInstance = autocomplete({
container: this.$refs.autocompleteContainer,
placeholder: 'Search for products',
detachedMediaQuery: 'none',
openOnFocus: true,
plugins: [
recentSearchesPlugin,
querySuggestionPluginInCategory,
querySuggestionsPlugin,
],
initialState: { query: initialState.query || '' },
onSubmit({ state }) {
setInstantSearchUiState({ query: state.query });
},
onReset() {
setInstantSearchUiState({ query: '', resetCategory: true });
},
onStateChange({ prevState, state }) {
if (prevState.query !== state.query) {
debouncedSetInstantSearchUiState({ query: state.query });
}
},
renderer: {
createElement,
Fragment,
},
render({ children }, root) {
render(children, root);
},
});
},
beforeUnmount() {},
};
</script>
Loading

0 comments on commit e011c0f

Please sign in to comment.