From a698c5cfca286270a6b9f6f49a778880f1098c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20Engstr=C3=B6m?= Date: Mon, 9 Sep 2024 10:50:32 +0200 Subject: [PATCH] LWS-218: Display spelling suggestions (#1098) * LWS-218: Display spelling suggestion --- .../lib/components/find/SearchRelated.svelte | 13 +++- .../lib/components/find/SearchResult.svelte | 61 +++++++++++-------- lxl-web/src/lib/i18n/locales/en.js | 3 +- lxl-web/src/lib/i18n/locales/sv.js | 3 +- lxl-web/src/lib/types/search.ts | 8 +++ .../lib/utils/addDefaultSearchParams.test.ts | 9 ++- .../src/lib/utils/addDefaultSearchParams.ts | 3 + lxl-web/src/lib/utils/search.ts | 10 ++- lxl-web/tests/index.spec.ts | 4 +- 9 files changed, 78 insertions(+), 36 deletions(-) diff --git a/lxl-web/src/lib/components/find/SearchRelated.svelte b/lxl-web/src/lib/components/find/SearchRelated.svelte index 2774f87bc..21e2d2ea7 100644 --- a/lxl-web/src/lib/components/find/SearchRelated.svelte +++ b/lxl-web/src/lib/components/find/SearchRelated.svelte @@ -1,7 +1,8 @@ -
+ {#if numHits && numHits > 0} - {#if numHits > searchResult.itemsPerPage} + + {#if numHits > searchResult.itemsPerPage} + + {(searchResult.itemOffset + 1).toLocaleString($page.data.locale)} + - + {Math.min( + numHits, + searchResult.itemOffset + searchResult.itemsPerPage + ).toLocaleString($page.data.locale)} + + {$page.data.t('search.hitsOf')} + {/if} - {(searchResult.itemOffset + 1).toLocaleString($page.data.locale)} - - - {Math.min( - numHits, - searchResult.itemOffset + searchResult.itemsPerPage - ).toLocaleString($page.data.locale)} + {numHits.toLocaleString($page.data.locale)} - {$page.data.t('search.hitsOf')} - {/if} - - {numHits.toLocaleString($page.data.locale)} + {#if $page.data.instances} + {numHits == 1 ? $page.data.t('search.relatedOne') : $page.data.t('search.related')} + {/if} + {numHits == 1 ? $page.data.t('search.hitsOne') : $page.data.t('search.hits')} - {#if $page.data.instances} - {numHits == 1 - ? $page.data.t('search.relatedOne') - : $page.data.t('search.related')} - {/if} - {numHits == 1 ? $page.data.t('search.hitsOne') : $page.data.t('search.hits')} {:else} - {$page.data.t('search.noResults')} + {$page.data.t('search.noResults')} + {/if} + {#if searchResult._spell.length > 0} + + {#each searchResult._spell as suggestion (suggestion.label)} + {$page.data.t('search.didYouMean')} + + + {@html suggestion.labelHtml}? + {/each} + {/if} {/if} - diff --git a/lxl-web/src/lib/i18n/locales/en.js b/lxl-web/src/lib/i18n/locales/en.js index c46e89b66..e85df4585 100644 --- a/lxl-web/src/lib/i18n/locales/en.js +++ b/lxl-web/src/lib/i18n/locales/en.js @@ -92,7 +92,8 @@ export default { showDetails: 'Show more', hideDetails: 'Show less', occursAs: 'as', - relatedSearchLabel: 'Search the results' + relatedSearchLabel: 'Search the results', + didYouMean: 'Did you mean' }, sort: { sort: 'Sort', diff --git a/lxl-web/src/lib/i18n/locales/sv.js b/lxl-web/src/lib/i18n/locales/sv.js index 536031019..44fc30cc8 100644 --- a/lxl-web/src/lib/i18n/locales/sv.js +++ b/lxl-web/src/lib/i18n/locales/sv.js @@ -91,7 +91,8 @@ export default { showDetails: 'Visa mer', hideDetails: 'Visa mindre', occursAs: 'förekommer som', - relatedSearchLabel: 'Sök i resultaten' + relatedSearchLabel: 'Sök i resultaten', + didYouMean: 'Menade du' }, sort: { sort: 'Sortera', diff --git a/lxl-web/src/lib/types/search.ts b/lxl-web/src/lib/types/search.ts index fc8903da4..b37f6fde7 100644 --- a/lxl-web/src/lib/types/search.ts +++ b/lxl-web/src/lib/types/search.ts @@ -15,6 +15,7 @@ export interface SearchResult { items: SearchResultItem[]; facetGroups: FacetGroup[]; predicates: MultiSelectFacet[]; + _spell: SpellingSuggestion[] | []; } export interface SearchResultItem { @@ -57,6 +58,12 @@ export interface MultiSelectFacet extends Facet { selected: boolean; } +interface SpellingSuggestion { + label: string; + labelHtml: string; + view: Link; +} + export interface DisplayMapping { '@id'?: string; display?: DisplayDecorated; @@ -87,6 +94,7 @@ export interface PartialCollectionView { _predicates: Observation[]; _boolFilters?: Observation[]; }; + _spell: SpellingSuggestion[] | []; } interface Slice { diff --git a/lxl-web/src/lib/utils/addDefaultSearchParams.test.ts b/lxl-web/src/lib/utils/addDefaultSearchParams.test.ts index ea54d41b1..4c14efa58 100644 --- a/lxl-web/src/lib/utils/addDefaultSearchParams.test.ts +++ b/lxl-web/src/lib/utils/addDefaultSearchParams.test.ts @@ -8,7 +8,8 @@ describe('addDefaultSearchParams', () => { ['_q', '*'], ['_limit', '20'], ['_offset', '0'], - ['_sort', ''] + ['_sort', ''], + ['_spell', 'true'] ]) ); }); @@ -18,7 +19,8 @@ describe('addDefaultSearchParams', () => { ['_q', 'test'], ['_limit', '20'], ['_offset', '0'], - ['_sort', ''] + ['_sort', ''], + ['_spell', 'true'] ]) ); }); @@ -28,7 +30,8 @@ describe('addDefaultSearchParams', () => { ['_offset', '30'], ['_q', '*'], ['_limit', '20'], - ['_sort', ''] + ['_sort', ''], + ['_spell', 'true'] ]) ); }); diff --git a/lxl-web/src/lib/utils/addDefaultSearchParams.ts b/lxl-web/src/lib/utils/addDefaultSearchParams.ts index c57fd61b0..c38fa8b4c 100644 --- a/lxl-web/src/lib/utils/addDefaultSearchParams.ts +++ b/lxl-web/src/lib/utils/addDefaultSearchParams.ts @@ -16,6 +16,9 @@ function addDefaultSearchParams(searchParams: URLSearchParams): URLSearchParams if (!params.has('_sort')) { params.set('_sort', ''); } + if (!params.has('_spell')) { + params.set('_spell', 'true'); + } return params; } diff --git a/lxl-web/src/lib/utils/search.ts b/lxl-web/src/lib/utils/search.ts index cb07998d3..db666e47a 100644 --- a/lxl-web/src/lib/utils/search.ts +++ b/lxl-web/src/lib/utils/search.ts @@ -63,7 +63,15 @@ export async function asResult( ) })), facetGroups: displayFacetGroups(view, displayUtil, locale, translate, usePath), - predicates: displayPredicates(view, displayUtil, locale, usePath) + predicates: displayPredicates(view, displayUtil, locale, usePath), + _spell: view._spell + ? view._spell.map((el) => { + return { + ...el, + ...{ view: replacePath(el.view, usePath) } + }; + }) + : [] }; } diff --git a/lxl-web/tests/index.spec.ts b/lxl-web/tests/index.spec.ts index 2372427dc..e0299be07 100644 --- a/lxl-web/tests/index.spec.ts +++ b/lxl-web/tests/index.spec.ts @@ -34,5 +34,7 @@ test('url is populated with correct searchparams', async ({ page }) => { await page.getByTestId('main-search').click(); await page.getByTestId('main-search').fill('somephrase'); await page.getByTestId('main-search').press('Enter'); - await expect(page).toHaveURL(/_q=somephrase&_limit=20&_offset=0&_sort=&_i=somephrase/); + await expect(page).toHaveURL( + /_q=somephrase&_limit=20&_offset=0&_sort=&_spell=true&_i=somephrase/ + ); });