Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(recent-searches): support search and templating #353

Merged
merged 5 commits into from
Nov 4, 2020

Conversation

francoischalifour
Copy link
Member

This PR is a new architecture of our Plugins API and of the Recent Searches Plugin that allows search and templating in the Recent Searches plugins. It also unlocks different Autocomplete use cases (same-page experience and redirect-page experience), as well as hooking other storages to Recent Searches.

Features

Storage abstraction

The storage is now abstracted and the Local Storage becomes one implementation that we support.

In the long run, we want to supported other storages to be able to sync Recent Searches on different devices (desktop, laptop, mobiles, etc.).

There's no conditional in the plugin itself, because the storage drives which items are returned. We therefore share a single plugin implementation for all plugins, only the storage differs.

Searching in Recent Searches

This new storage abstraction has allowed to export two distinct plugins:

  • createLocalStorageRecentSearchesPlugin: the plugin that we've known so far. It displays Recent Searches on empty query, and nothing when there's a query.
  • createSearchableLocalStorageRecentSearchesPlugin: the plugin that also display Recent Searches when there's a query, and searches in them. The search is currently only a startsWith check and doesn't support highlighting.

Again, the only difference between this two plugins are the storage implementation.

Shared limit between Recent Searches and Query Suggestions

The way results are shared between Recent Searches and Query Suggestions got more clever. They're now supporting "grouping limit". I created a Data Plugin API called getQuerySuggestionsHitsPerPage that allows to retrieve a number of "RS + QS" hitsPerPage value.

This feature avoid jumping UI and provides a seamless RS + QS integration:

autocomplete-rs-qs-grouped-limit

Templating

Since the logic about conditional displaying in now only on the storage, we can share templating options to all kinds of Recent Searches plugin.

We now support a getTemplates API that allows to override the template displayed by the plugin. This getTemplates API is used internally to provide the default template. The prop onRemove is passed so that our logic remains internal and doesn't leak (reminder: internally, it calls store.remove and refresh).

Here's a preview using Preact:

 const recentSearches = createSearchableLocalStorageRecentSearchesPlugin({
  key: 'recent',
  getTemplates({ onRemove }) {
    return {
      item({ item, root }) {
        render(<Item onRemove={onRemove}>{item.label}</Item>, root);
      },
    };
  },
});

This new API covers the second Recent Searches experience we wanted to unlock: redirect-page results. You can now provide a link to wrap your item in.

import {
  createSearchableLocalStorageRecentSearchesPlugin,
  getTemplates,
} from '@algolia/autocomplete-plugin-recent-searches';

const recentSearches = createSearchableLocalStorageRecentSearchesPlugin({
  key: 'recent',
  getTemplates({ onRemove }) {
    const originalTemplates = getTemplates({ onRemove });

    return {
      item({ item, root }) {
        const link = document.createElement('a');
        link.href = `https://google.com?q=${item.query}`;

        originalTemplates.item({ item, root: link });

        root.appendChild(link);
      },
    };
  },
});

Future API changes

  • subscribed.onSelect should not be called when the current source is selected

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 2, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 4ecb9ee:

Sandbox Source
@algolia/js-example Configuration

@francoischalifour
Copy link
Member Author

francoischalifour commented Nov 3, 2020

After syncing with @Haroenv we decided on a few changes that'll make the API more flexible—see 1d7e6bf.

Exporting createRecentSearchesPlugin

createRecentSearchesPlugin contains the logic around the Autocomplete plugin. It accepts two options:

  • storage
  • getTemplates

If its source.getItems (which calls storage.getAll(query)) returns no items, we don't add the source to Autocomplete.

We exports createLocalStorageRecentSearchesPlugin which is an implementation of it.

createLocalStorageRecentSearchesPlugin searches in RS by default

By default, the local storage plugin searches in the local storage, you can bail-out of this behavior with the search option.

Introducing the search method on createLocalStorageRecentSearchesPlugin

To remove the search feature:

const recentSearches = createLocalStorageRecentSearchesPlugin({
  key: 'recent',
  limit: 3,
  search({ query, items }) {
    if (query) {
      return [];
    }

    return items;
  },
});

To implement your own search strategy:

const recentSearches = createLocalStorageRecentSearchesPlugin({
  key: 'recent',
  limit: 3,
  search({ query, items }) {
    return items.filter((x) => x.query.includes(query));
  },
});

Next steps

We'll work soon on highlighting in another PR.

*
* @default 5
*/
limit?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the other api is using hitsPerPage, but this doesn't have pagination per se. Could it make sense to have hitsPerPage already even if pagination isn't yet implemented?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw a bit lower in this file hitsPerPage being around searchParameters, but here we are using limit for the argument. If we call this hitsPerPage, the API is one word smaller I think

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hitsPerPage is a concept in Algolia, and the Recent Searches plugin is not tied to Algolia, so I'm not sure about that.

This makes me think that the data properties that we have should probably contain the word Algolia. I'll change that.

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some great improvements here! let's make sure this is marked as a breaking change in the alpha changelog

Copy link
Contributor

@eunjae-lee eunjae-lee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look good to me 👍

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good for this pr, you can make the algolia changes in a subsequent one

@francoischalifour francoischalifour merged commit b8ff178 into next Nov 4, 2020
@francoischalifour francoischalifour deleted the feat/recent-searches-plugin-1 branch November 4, 2020 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants