Skip to content

Commit

Permalink
feat(noResults): allow providing URL to report missing results (#1289)
Browse files Browse the repository at this point in the history
shortcuts authored Feb 2, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent e324f4c commit 2c1fe7c
Showing 7 changed files with 149 additions and 41 deletions.
1 change: 1 addition & 0 deletions packages/docsearch-react/src/DocSearch.tsx
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ export interface DocSearchProps {
initialQuery?: string;
navigator?: AutocompleteOptions<InternalDocSearchHit>['navigator'];
translations?: DocSearchTranslations;
getMissingResultsUrl?: ({ query: string }) => string;
}

export function DocSearch(props: DocSearchProps) {
2 changes: 2 additions & 0 deletions packages/docsearch-react/src/DocSearchModal.tsx
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@ export function DocSearchModal({
disableUserPersonalization = false,
initialQuery: initialQueryFromProp = '',
translations = {},
getMissingResultsUrl,
}: DocSearchModalProps) {
const {
footer: footerTranslations,
@@ -429,6 +430,7 @@ export function DocSearchModal({
favoriteSearches={favoriteSearches}
inputRef={inputRef}
translations={screenStateTranslations}
getMissingResultsUrl={getMissingResultsUrl}
onItemClick={(item) => {
saveRecentSearch(item);
onClose();
31 changes: 16 additions & 15 deletions packages/docsearch-react/src/NoResultsScreen.tsx
Original file line number Diff line number Diff line change
@@ -7,8 +7,8 @@ import type { InternalDocSearchHit } from './types';
export type NoResultsScreenTranslations = Partial<{
noResultsText: string;
suggestedQueryText: string;
openIssueText: string;
openIssueLinkText: string;
reportMissingResultsText: string;
reportMissingResultsLinkText: string;
}>;

type NoResultsScreenProps = Omit<
@@ -25,8 +25,8 @@ export function NoResultsScreen({
const {
noResultsText = 'No results for',
suggestedQueryText = 'Try searching for',
openIssueText = 'Believe this query should return results?',
openIssueLinkText = 'Let us know',
reportMissingResultsText = 'Believe this query should return results?',
reportMissingResultsLinkText = 'Let us know.',
} = translations;
const searchSuggestions: string[] | undefined = props.state.context
.searchSuggestions as string[];
@@ -68,17 +68,18 @@ export function NoResultsScreen({
</div>
)}

<p className="DocSearch-Help">
{`${openIssueText} `}
<a
href={`https://github.com/algolia/docsearch-configs/issues/new?template=Missing_results.md&title=[${props.indexName}]+Missing+results+for+query+"${props.state.query}"`}
target="_blank"
rel="noopener noreferrer"
>
{openIssueLinkText}
</a>
.
</p>
{props.getMissingResultsUrl && (
<p className="DocSearch-Help">
{`${reportMissingResultsText} `}
<a
href={props.getMissingResultsUrl({ query: props.state.query })}
target="_blank"
rel="noopener noreferrer"
>
{reportMissingResultsLinkText}
</a>
</p>
)}
</div>
);
}
1 change: 1 addition & 0 deletions packages/docsearch-react/src/ScreenState.tsx
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@ export interface ScreenStateProps<TItem extends BaseItem>
disableUserPersonalization: boolean;
resultsFooterComponent: DocSearchProps['resultsFooterComponent'];
translations: ScreenStateTranslations;
getMissingResultsUrl?: DocSearchProps['getMissingResultsUrl'];
}

export const ScreenState = React.memo(
112 changes: 90 additions & 22 deletions packages/docsearch-react/src/__tests__/api.test.tsx
Original file line number Diff line number Diff line change
@@ -16,6 +16,27 @@ function DocSearch(props: Partial<DocSearchProps>) {
return <DocSearchComponent apiKey="foo" indexName="bar" {...props} />;
}

// mock empty response
function noResultSearch(_queries: any, _requestOptions?: any): Promise<any> {
return new Promise((resolve) => {
resolve({
results: [
{
hits: [],
hitsPerPage: 0,
nbHits: 0,
nbPages: 0,
page: 0,
processingTimeMS: 0,
exhaustiveNbHits: true,
params: '',
query: '',
},
],
});
});
}

describe('api', () => {
beforeEach(() => {
document.body.innerHTML = '';
@@ -71,40 +92,23 @@ describe('api', () => {
it('overrides the default DocSearchModal noResultsScreen text', async () => {
render(
<DocSearch
// mock empty response
transformSearchClient={(searchClient) => {
return {
...searchClient,
search: () => {
return new Promise((resolve) => {
resolve({
results: [
{
hits: [],
hitsPerPage: 0,
nbHits: 0,
nbPages: 0,
page: 0,
processingTimeMS: 0,
exhaustiveNbHits: true,
params: '',
query: '',
},
],
});
});
},
search: noResultSearch,
};
}}
translations={{
modal: {
noResultsScreen: {
noResultsText: 'Pas de résultats pour',
openIssueText: 'Ouvrez une issue sur docsearch-configs',
openIssueLinkText: 'Lien du repo',
reportMissingResultsText:
'Ouvrez une issue sur docsearch-configs',
reportMissingResultsLinkText: 'Lien du repo',
},
},
}}
getMissingResultsUrl={() => 'algolia.com'}
/>
);

@@ -190,4 +194,68 @@ describe('api', () => {
expect(screen.getByText('Selectionner')).toBeInTheDocument();
});
});

describe('getMissingResultsUrl', () => {
it('does not render the link to the repository by default', async () => {
render(
<DocSearch
transformSearchClient={(searchClient) => {
return {
...searchClient,
search: noResultSearch,
};
}}
/>
);

await act(async () => {
await waitFor(() => {
fireEvent.click(document.querySelector('.DocSearch-Button'));
});

fireEvent.input(document.querySelector('.DocSearch-Input'), {
target: { value: 'q' },
});
});

expect(screen.getByText(/No results for/)).toBeInTheDocument();
expect(
document.querySelector('.DocSearch-Help a')
).not.toBeInTheDocument();
});

it('render the link to the repository', async () => {
render(
<DocSearch
transformSearchClient={(searchClient) => {
return {
...searchClient,
search: noResultSearch,
};
}}
getMissingResultsUrl={({ query }) =>
`https://github.com/algolia/docsearch/issues/new?title=${query}`
}
/>
);

await act(async () => {
await waitFor(() => {
fireEvent.click(document.querySelector('.DocSearch-Button'));
});

fireEvent.input(document.querySelector('.DocSearch-Input'), {
target: { value: 'q' },
});
});

expect(screen.getByText(/No results for/)).toBeInTheDocument();

const link = document.querySelector('.DocSearch-Help a');
expect(link).toBeInTheDocument();
expect(link.getAttribute('href')).toBe(
'https://github.com/algolia/docsearch/issues/new?title=q'
);
});
});
});
43 changes: 39 additions & 4 deletions packages/website/docs/api.mdx
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ title: API Reference

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import useBaseUrl from '@docusaurus/useBaseUrl';

:::info

@@ -160,8 +161,8 @@ const translations: DocSearchTranslations = {
noResultsScreen: {
noResultsText: 'No results for',
suggestedQueryText: 'Try searching for',
openIssueText: 'Believe this query should return results?',
openIssueLinkText: 'Let us know',
reportMissingResultsText: 'Believe this query should return results?',
reportMissingResultsLinkText: 'Let us know.',
},
},
};
@@ -170,6 +171,23 @@ const translations: DocSearchTranslations = {
</div>
</details>

## `getMissingResultsUrl`

> `type: ({ query: string }) => string` | **optional**
> example: ({ query }) => `https://github.com/algolia/docsearch/issues/new?title=${query}`
Function to return the URL of your documentation repository.

When provided, an informative message wrapped with your link will be displayed on no results searches. The default text can be changed using the [translations](#translations) property.

<div className="uil-ta-center">
<img
src={useBaseUrl('img/assets/noResultsScreen.png')}
alt="No results screen with informative message"
/>
</div>

</TabItem>

<TabItem value="react">
@@ -299,8 +317,8 @@ const translations: DocSearchTranslations = {
noResultsScreen: {
noResultsText: 'No results for',
suggestedQueryText: 'Try searching for',
openIssueText: 'Believe this query should return results?',
openIssueLinkText: 'Let us know',
reportMissingResultsText: 'Believe this query should return results?',
reportMissingResultsLinkText: 'Let us know.',
},
},
};
@@ -309,6 +327,23 @@ const translations: DocSearchTranslations = {
</div>
</details>

## `getMissingResultsUrl`

> `type: ({ query: string }) => string` | **optional**
> example: ({ query }) => `https://github.com/algolia/docsearch/issues/new?title=${query}`
Function to return the URL of your documentation repository.

When provided, an informative message wrapped with your link will be displayed on no results searches. The default text can be changed using the [translations](#translations) property.

<div className="uil-ta-center">
<img
src={useBaseUrl('img/assets/noResultsScreen.png')}
alt="No results screen with informative message"
/>
</div>

</TabItem>

</Tabs>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2c1fe7c

Please sign in to comment.