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(core): provide information about stalled search to widgets #2569

Merged
merged 23 commits into from
Nov 28, 2017

Conversation

bobylito
Copy link
Contributor

@bobylito bobylito commented Nov 9, 2017

This PR is an alternative implementation of #2509. This is currently a PoC.

At the core of this new implementation is a change when the render part of the lifecycle of the widget. With this implementation, the render can be called when the instantsearch detects that a search is stalled. This means that they will be called more often. However, this is not likely to have a big impact on the performance as it should be the responsability of the widgets to render only when necessary.

On the implementation of the connector and the widget, the work is trivial. It is merely a question of providing the isSearchStalled flag to the rendering. The logic is factored in instantsearch, which means that the usage in other widgets will be as easy.

Having done this implementation, I think it's the way to go. WDYT? Happy to answer any questions.

PS: this new implementation has been inspired by what can be done in react-instantsearch and vue-instantsearch. If we were to implement them using this library, this means that we need to fit their logic.

PPS: this can be tested here: https://deploy-preview-2569--algolia-instantsearch.netlify.com/v2/dev-novel/?selectedStory=SearchBox.default

Alex S added 2 commits November 9, 2017 19:37
This commit adds a new step that can update the UI. In this change,
the widgets are rendered when there are new results (previous behaviour)
and when the search is found to be stalled. The information is
propagated through a new option `searchMetadata` to the render method of
the widgets. This is an object that contains the flag `isStalledSearch`
that is set to `true` when there are still pending search after a delay
(for now 200ms).
@algobot
Copy link
Contributor

algobot commented Nov 9, 2017

Deploy preview ready!

Built with commit 737d28e

https://deploy-preview-2569--algolia-instantsearch.netlify.com

Copy link
Contributor

@samouss samouss left a comment

Choose a reason for hiding this comment

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

Nice 👍

I clearly prefer this implementation since it's not tightly coupled to the SearchBox widget 🎉

@vvo
Copy link
Contributor

vvo commented Nov 10, 2017

I like the implementation, as discussed earlier in a meeting, some questions still:

However, this is not likely to have a big impact on the performance
Can you try a small manual perf test in the browser to see if there's any obvious issue/diff with this implementation?

It should be the responsability of the widgets to render only when necessary.

Can you provide an example of a widget rendering that would avoid re-rendering when the widget do not care about the isSearchStalled flag? Just curious here how to do it.

Finally, for reference, can you provide a small concrete example of what's happening under the hood in a scenario where this is implemented? Something like:

  • user types 'a'
  • flag becomes true
  • widget render once..

Something like that. So that we all understand fully what's happening.

@Haroenv
Copy link
Contributor

Haroenv commented Nov 10, 2017

This looks really nice, I think we should go this route. I guess we can add some componentShouldUpate hooks?

@bobylito
Copy link
Contributor Author

Can you provide an example of a widget rendering that would avoid re-rendering when the widget do not care about the isSearchStalled flag? Just curious here how to do it.

That's a very speculative on my side here I guess. I can try to implement it on a widget / connector to see what happens.

Something like that. So that we all understand fully what's happening.

Ok I'll do a schema.

This looks really nice, I think we should go this route. I guess we can add some componentShouldUpate hooks?

I don't know if that's necessary but that can be done, indeed.

@bobylito
Copy link
Contributor Author

bobylito commented Nov 16, 2017

I will move on with this solution and close the other. Thanks for the feedbacks :)

@bobylito
Copy link
Contributor Author

new rendering step visually

@bobylito
Copy link
Contributor Author

bobylito commented Nov 24, 2017

Hello everyone,

This is the final version. Here is the API:

InstantSearch constructor / factory has a new option: stalledSearchDelay which configures the time before the stalled search kicks in.
Also InstantSearch provides a new searchMetadata attribute with the options sent to the widgets at render. It's not provided at init because there is no search yet (therefore no metadata about search). The searchMetadata is an object with a single key isSearchStalled.

We have a new set of options for the loading indicator on the search box:

{
  /* ... other searchbox options */
  loadingIndicator: true,
  // or
  loadingIndicator: {
    template,
    cssClasses: {root: ''}
  } 
}

The connector provides a new information to the searchbox rendering: isSearchStalled, if the search is stalled.

@Haroenv
Copy link
Contributor

Haroenv commented Nov 24, 2017

CI failed cause one commit message was too long (merge 1d0aa21) so you might need to rebase

@bobylito
Copy link
Contributor Author

Thanks @Haroenv :D

Alex S added 2 commits November 24, 2017 20:02
Merge commits are automatically generated and are already standardized
by git, therefore there is no point in checking their length. Worst
truncating them would make use loose information.
Copy link
Contributor

@samouss samouss left a comment

Choose a reason for hiding this comment

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

Good job 👍

I just left two comments on documentation.

/**
* @typedef {Object} SearchBoxLoadingIndicatorOption
* @property {function|string} template Template used for displaying the button. Can accept a function or a Hogan string.
* @property {{root: string}} [cssClasses] CSS classes added to the reset buton.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be the loading indicator root element.

@@ -173,8 +207,9 @@ searchBox({
* @property {string|HTMLElement} container CSS Selector or HTMLElement to insert the widget.
* @property {string} [placeholder] Input's placeholder.
* @property {boolean|SearchBoxPoweredByOption} [poweredBy=false] Define if a "powered by Algolia" link should be added near the input.
* @property {boolean|SearchBoxResetOption} [reset=true] Define if a reset button should be added in the input when there is a query.
* @property {boolean|SearchBoxResetOption} [reset=false] Define if a reset button should be added in the input when there is a query.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it an intended change? The default value is still true in the code.

@@ -35,6 +35,8 @@ Full documentation available at https://community.algolia.com/instantsearch.js/c
* @property {function(string)} refine Sets a new query and searches.
* @property {function()} clear Remove the query and perform search.
* @property {Object} widgetParams All original `CustomSearchBoxWidgetOptions` forwarded to the `renderFn`.
* @property {boolean} isSearchStalled `true` if the search results takes more than a certain time to come back
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we document "a certain time"? I would be curious as a dev to know more. This may be too vague

Copy link
Contributor Author

Choose a reason for hiding this comment

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

indeed there is a default value. Will doc that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done (only happen a few lines after :))


if (loadingIndicator) {
if (isSearchStalled) {
containerNode.firstChild.classList.add('stalled-search');
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this CSS class name follow ais- conventions? And be documented somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yes sure. Also it doesn't work if you use an input as container :/

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe document that part, but I won't be surprised as a dev for it not to be supported.

@@ -173,8 +207,9 @@ searchBox({
* @property {string|HTMLElement} container CSS Selector or HTMLElement to insert the widget.
* @property {string} [placeholder] Input's placeholder.
* @property {boolean|SearchBoxPoweredByOption} [poweredBy=false] Define if a "powered by Algolia" link should be added near the input.
* @property {boolean|SearchBoxResetOption} [reset=true] Define if a reset button should be added in the input when there is a query.
* @property {boolean|SearchBoxResetOption} [reset=false] Define if a reset button should be added in the input when there is a query.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it false by default now to have a reset button?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will double check 👍

* @property {boolean|SearchBoxMagnifierOption} [magnifier=true] Define if a magnifier should be added at beginning of the input to indicate a search input.
* @property {boolean|SearchBoxLoadingIndicatorOption} [loadingIndicator=false] Define if a loading indicator should be added at beginning of the input to indicate that search is currently stalled.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we make it true by default, since it's a new feature and might bring good behaviour by default?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was wondering. The idea behind false by default is that we don't change any existing behavior / style, especially if the user doesn't use the provided stylesheets.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep that's the safest, if we were to do a new breaking version we would make it true by default, cc @mthuret can we add that to the feedback/product loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Happy to break in v3 ;)

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed, false for now, breaking to true in v3 👍

@bobylito
Copy link
Contributor Author

The behavior and loading indicator have been validated by @sebnvzt :D

Copy link
Contributor

@iam4x iam4x left a comment

Choose a reason for hiding this comment

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

Love it, very nice work @bobylito 👍

@bobylito bobylito changed the base branch from develop to feat/2.3 November 27, 2017 17:39
@bobylito bobylito merged commit d104be1 into feat/2.3 Nov 28, 2017
@bobylito bobylito deleted the poc/central-loading-state branch November 28, 2017 14:45
bobylito pushed a commit that referenced this pull request Nov 30, 2017
<a name=2.3.0></a>
# [2.3.0](v2.3.0-beta.7...v2.3.0) (2017-11-30)

### Bug Fixes

* **InstantSearch.dispose:** dont call  of URLSync widget ([#2604](#2604)) ([3234b12](3234b12))

### Features

* **core:** provide information about stalled search to widgets ([#2569](#2569)) ([d104be1](d104be1))
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.

6 participants