From fbfca35e99002c27d3b79f79aa91a10fde2bdf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Vannicatte?= <20689156+shortcuts@users.noreply.github.com> Date: Wed, 20 Jan 2021 13:43:58 +0100 Subject: [PATCH] feat(emptyStates): implements empty source template and renderEmpty method (#395) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implements `empty` template and `renderEmpty` method * Add wait function to `test/utils` folder Co-authored-by: François Chalifour --- examples/js/app.ts | 94 +++++++++++++++++++ .../src/__tests__/autocomplete.test.ts | 7 +- packages/autocomplete-js/src/autocomplete.ts | 10 ++ test/utils/index.ts | 1 + test/utils/wait.ts | 5 + 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 examples/js/app.ts create mode 100644 test/utils/wait.ts diff --git a/examples/js/app.ts b/examples/js/app.ts new file mode 100644 index 000000000..14402393e --- /dev/null +++ b/examples/js/app.ts @@ -0,0 +1,94 @@ +import { + autocomplete, + getAlgoliaHits, + reverseHighlightHit, +} from '@algolia/autocomplete-js'; +import { createAlgoliaInsightsPlugin } from '@algolia/autocomplete-plugin-algolia-insights'; +import { createQuerySuggestionsPlugin } from '@algolia/autocomplete-plugin-query-suggestions'; +import { createLocalStorageRecentSearchesPlugin } from '@algolia/autocomplete-plugin-recent-searches'; +import algoliasearch from 'algoliasearch'; +import insightsClient from 'search-insights'; + +import '@algolia/autocomplete-theme-classic'; + +const appId = 'latency'; +const apiKey = '6be0576ff61c053d5f9a3225e2a90f76'; +const searchClient = algoliasearch(appId, apiKey); +insightsClient('init', { appId, apiKey }); + +const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({ insightsClient }); +const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ + key: 'search', + limit: 3, +}); +const querySuggestionsPlugin = createQuerySuggestionsPlugin({ + searchClient, + indexName: 'instant_search_demo_query_suggestions', + getSearchParams() { + return recentSearchesPlugin.data.getAlgoliaSearchParams({ + clickAnalytics: true, + }); + }, +}); + +autocomplete({ + container: '#autocomplete', + placeholder: 'Search', + openOnFocus: true, + plugins: [ + algoliaInsightsPlugin, + recentSearchesPlugin, + querySuggestionsPlugin, + ], + getSources({ query }) { + if (!query) { + return []; + } + + return [ + { + getItems() { + return getAlgoliaHits({ + searchClient, + queries: [{ indexName: 'instant_search', query }], + }); + }, + templates: { + item({ item, root }) { + const itemContent = document.createElement('div'); + const ItemSourceIcon = document.createElement('div'); + const itemTitle = document.createElement('div'); + const sourceIcon = document.createElement('img'); + + sourceIcon.width = 20; + sourceIcon.height = 20; + sourceIcon.src = item.image; + + ItemSourceIcon.classList.add('aa-ItemSourceIcon'); + ItemSourceIcon.appendChild(sourceIcon); + + itemTitle.innerHTML = reverseHighlightHit({ + hit: item, + attribute: 'name', + }); + itemTitle.classList.add('aa-ItemTitle'); + + itemContent.classList.add('aa-ItemContent'); + itemContent.appendChild(ItemSourceIcon); + itemContent.appendChild(itemTitle); + + root.appendChild(itemContent); + }, + empty({ root }) { + const itemContent = document.createElement('div'); + + itemContent.innerHTML = 'No results for this query'; + itemContent.classList.add('aa-ItemContent'); + + root.appendChild(itemContent); + }, + }, + }, + ]; + }, +}); diff --git a/packages/autocomplete-js/src/__tests__/autocomplete.test.ts b/packages/autocomplete-js/src/__tests__/autocomplete.test.ts index 23035ae68..240359ddb 100644 --- a/packages/autocomplete-js/src/__tests__/autocomplete.test.ts +++ b/packages/autocomplete-js/src/__tests__/autocomplete.test.ts @@ -1,5 +1,6 @@ import { fireEvent, waitFor } from '@testing-library/dom'; +import { wait } from '../../../../test/utils'; import { autocomplete } from '../autocomplete'; describe('autocomplete-js', () => { @@ -92,8 +93,8 @@ describe('autocomplete-js', () => { stroke-dasharray="164.93361431346415 56.97787143782138" stroke-width="6" > - - + + { type="rotate" values="0 50 50;90 50 50;180 50 50;360 50 50" /> - + diff --git a/packages/autocomplete-js/src/autocomplete.ts b/packages/autocomplete-js/src/autocomplete.ts index fdd248d52..bcc026da5 100644 --- a/packages/autocomplete-js/src/autocomplete.ts +++ b/packages/autocomplete-js/src/autocomplete.ts @@ -150,6 +150,16 @@ export function autocomplete( props.value.renderer.renderEmpty) || props.value.renderer.render; + hasEmptySourceTemplateRef.current = renderProps.state.collections.some( + (collection) => collection.source.templates.empty + ); + + const render = + (!getItemsCount(renderProps.state) && + !hasEmptySourceTemplateRef.current && + props.value.renderer.renderEmpty) || + props.value.renderer.render; + renderSearchBox(renderProps); renderPanel(render, renderProps); } diff --git a/test/utils/index.ts b/test/utils/index.ts index 912a9c3f6..551720c4d 100644 --- a/test/utils/index.ts +++ b/test/utils/index.ts @@ -8,3 +8,4 @@ export * from './createSource'; export * from './createState'; export * from './defer'; export * from './runAllMicroTasks'; +export * from './wait'; diff --git a/test/utils/wait.ts b/test/utils/wait.ts new file mode 100644 index 000000000..a68b7baa2 --- /dev/null +++ b/test/utils/wait.ts @@ -0,0 +1,5 @@ +export function wait(time: number) { + return new Promise((resolve) => { + setTimeout(resolve, time); + }); +}