From ddaf941e1758b1520649f2f359f079ec6e85f905 Mon Sep 17 00:00:00 2001 From: Haroen Viaene Date: Fri, 25 Jun 2021 16:12:05 +0200 Subject: [PATCH] feat(facetOrdering): add a new option "facetOrdering" to Menu, RefinementList & HierarchicalMenu If `facetOrdering` is enabled (the default behaviour), before the default sortBy is used, the result from renderingContent.facetOrdering.values is first checked. If that's present, it will be used to sort the items. You can still change that ordering afterwards with the existing transformItems, so if you are sorting in transformItems, you actually override the sorting done by facet ordering, and won't see the effect. To use facetOrdering, you thus need to remove any sorting done in transformItems. If there is a facetOrdering present in the index, but you don't want to use it for a certain widget, you need to explicitly pass `facetOrdering: false` to the widget or connector References: - [RFC 45](https://github.com/algolia/instantsearch-rfcs/blob/master/accepted/flexible-facet-values.md) - https://github.com/algolia/instantsearch.js/pull/4784 - https://github.com/algolia/algoliasearch-helper-js/pull/822 --- examples/autocomplete/package.json | 2 +- examples/default-theme/package.json | 2 +- examples/e-commerce/package.json | 2 +- examples/geo-search/package.json | 2 +- examples/media/package.json | 2 +- examples/multi-index/package.json | 2 +- examples/next/package.json | 2 +- .../package.json | 2 +- examples/react-native/package.json | 2 +- examples/react-router-v3/package.json | 2 +- examples/react-router/package.json | 2 +- examples/server-side-rendering/package.json | 2 +- examples/tourism/package.json | 2 +- package.json | 2 +- .../react-instantsearch-core/package.json | 2 +- .../__tests__/connectHierarchicalMenu.js | 154 ++++++++++++++- .../src/connectors/__tests__/connectMenu.js | 123 +++++++++++- .../__tests__/connectRefinementList.js | 112 ++++++++++- .../src/connectors/connectHierarchicalMenu.js | 6 +- .../src/connectors/connectMenu.js | 5 +- .../src/connectors/connectRefinementList.js | 6 +- .../src/core/indexUtils.js | 3 + packages/react-instantsearch-dom/package.json | 2 +- yarn.lock | 178 +++++++++++------- 24 files changed, 528 insertions(+), 91 deletions(-) diff --git a/examples/autocomplete/package.json b/examples/autocomplete/package.json index 2732fbd313..e59281d1a9 100644 --- a/examples/autocomplete/package.json +++ b/examples/autocomplete/package.json @@ -13,7 +13,7 @@ "react-test-renderer": "16.8.6" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "antd": "3.23.2", "lodash": "4.17.15", "prop-types": "15.6.0", diff --git a/examples/default-theme/package.json b/examples/default-theme/package.json index 3100b674b0..0ea11223d2 100644 --- a/examples/default-theme/package.json +++ b/examples/default-theme/package.json @@ -3,7 +3,7 @@ "version": "6.11.1", "private": true, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "qs": "6.8.0", "react": "16.8.6", "react-dom": "16.8.6", diff --git a/examples/e-commerce/package.json b/examples/e-commerce/package.json index 2d77fa40f1..0cd0e4a552 100644 --- a/examples/e-commerce/package.json +++ b/examples/e-commerce/package.json @@ -3,7 +3,7 @@ "version": "6.11.1", "private": true, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "classnames": "2.2.6", "qs": "6.8.0", "react": "16.8.6", diff --git a/examples/geo-search/package.json b/examples/geo-search/package.json index 9cfa2c9711..b9c6d94f5a 100644 --- a/examples/geo-search/package.json +++ b/examples/geo-search/package.json @@ -13,7 +13,7 @@ "react-test-renderer": "16.8.6" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "instantsearch.css": "7.3.1", "qs": "6.8.0", "react": "16.8.6", diff --git a/examples/media/package.json b/examples/media/package.json index 10b8b5d296..1f7a0ed777 100644 --- a/examples/media/package.json +++ b/examples/media/package.json @@ -3,7 +3,7 @@ "version": "6.11.1", "private": true, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "qs": "6.8.0", "react": "16.8.6", "react-dom": "16.8.6", diff --git a/examples/multi-index/package.json b/examples/multi-index/package.json index f4328fbae2..26b350dd05 100644 --- a/examples/multi-index/package.json +++ b/examples/multi-index/package.json @@ -13,7 +13,7 @@ "react-test-renderer": "16.8.6" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "instantsearch.css": "7.3.1", "prop-types": "15.6.0", "react": "16.8.6", diff --git a/examples/next/package.json b/examples/next/package.json index 7806c0e3bd..d7248c19ca 100644 --- a/examples/next/package.json +++ b/examples/next/package.json @@ -18,7 +18,7 @@ "style-loader": "1.0.0" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "next": "9.1.1", "prop-types": "15.6.2", "qs": "6.8.0", diff --git a/examples/react-native-query-suggestions/package.json b/examples/react-native-query-suggestions/package.json index 52b83ab65c..3d8bb1d829 100644 --- a/examples/react-native-query-suggestions/package.json +++ b/examples/react-native-query-suggestions/package.json @@ -12,7 +12,7 @@ "test": "jest" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "expo": "37.0.3", "lodash": "4.17.15", "prop-types": "15.6.2", diff --git a/examples/react-native/package.json b/examples/react-native/package.json index 0033a07564..a1038c7706 100644 --- a/examples/react-native/package.json +++ b/examples/react-native/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@ptomasroos/react-native-multi-slider": "2.2.2", - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "expo": "37.0.3", "lodash": "4.17.15", "prop-types": "15.6.2", diff --git a/examples/react-router-v3/package.json b/examples/react-router-v3/package.json index 2fe7845929..1b5bf79f86 100644 --- a/examples/react-router-v3/package.json +++ b/examples/react-router-v3/package.json @@ -13,7 +13,7 @@ "react-test-renderer": "16.8.6" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "instantsearch.css": "7.3.1", "lodash": "4.17.15", "prop-types": "15.6.0", diff --git a/examples/react-router/package.json b/examples/react-router/package.json index 3e80e1fc50..96f53b66a9 100644 --- a/examples/react-router/package.json +++ b/examples/react-router/package.json @@ -14,7 +14,7 @@ "react-test-renderer": "16.8.6" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "instantsearch.css": "7.3.1", "lodash": "4.17.15", "prop-types": "15.6.0", diff --git a/examples/server-side-rendering/package.json b/examples/server-side-rendering/package.json index 16348d8274..11be27cbe6 100644 --- a/examples/server-side-rendering/package.json +++ b/examples/server-side-rendering/package.json @@ -26,7 +26,7 @@ "webpack-node-externals": "1.7.2" }, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "express": "4.17.1", "prop-types": "15.6.0", "react": "16.8.6", diff --git a/examples/tourism/package.json b/examples/tourism/package.json index 13540a9b89..e9f3b848e2 100644 --- a/examples/tourism/package.json +++ b/examples/tourism/package.json @@ -3,7 +3,7 @@ "version": "6.11.1", "private": true, "dependencies": { - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "qs": "6.8.0", "react": "16.8.6", "react-dom": "16.8.6", diff --git a/package.json b/package.json index 2062301517..a1d4a8ad37 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "@wdio/selenium-standalone-service": "5.16.10", "@wdio/spec-reporter": "5.16.11", "@wdio/static-server-service": "5.16.10", - "algoliasearch": "4.8.5", + "algoliasearch": "4.9.3", "argos-cli": "0.1.3", "babel-eslint": "10.0.2", "babel-jest": "24.9.0", diff --git a/packages/react-instantsearch-core/package.json b/packages/react-instantsearch-core/package.json index 0e0592f85a..1e8e68b855 100644 --- a/packages/react-instantsearch-core/package.json +++ b/packages/react-instantsearch-core/package.json @@ -37,7 +37,7 @@ }, "dependencies": { "@babel/runtime": "^7.1.2", - "algoliasearch-helper": "^3.4.3", + "algoliasearch-helper": "^3.5.3", "prop-types": "^15.6.2", "react-fast-compare": "^3.0.0" }, diff --git a/packages/react-instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.js b/packages/react-instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.js index b49fbb5232..1d9d2a9f4b 100644 --- a/packages/react-instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.js +++ b/packages/react-instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.js @@ -1,4 +1,4 @@ -import { SearchParameters } from 'algoliasearch-helper'; +import { SearchResults, SearchParameters } from 'algoliasearch-helper'; import connect from '../connectHierarchicalMenu'; jest.mock('../../core/createConnector', () => x => x); @@ -174,6 +174,158 @@ describe('connectHierarchicalMenu', () => { expect(props.items).toEqual(['items']); }); + it('facetValues results uses facetOrdering by default', () => { + const props = { + ...connect.defaultProps, + attributes: ['lvl0', 'lvl1'], + contextValue, + }; + const searchState = { hierarchicalMenu: { lvl0: 'wat' } }; + const state = connect.getSearchParameters( + new SearchParameters(), + props, + searchState + ); + const results = new SearchResults(state, [ + { + hits: [], + renderingContent: { + facetOrdering: { + values: { + lvl0: { + order: ['wat'], + }, + lvl1: { + order: ['wat > wut'], + }, + }, + }, + }, + facets: { + lvl0: { + wat: 20, + oy: 10, + }, + lvl1: { + 'wat > wot': 15, + 'wat > wut': 5, + }, + }, + }, + ]); + + const providedProps = connect.getProvidedProps(props, searchState, { + results, + }); + expect(providedProps.items).toEqual([ + { + label: 'wat', + value: undefined, + count: 20, + isRefined: true, + items: [ + { + label: 'wut', + value: 'wat > wut', + count: 5, + isRefined: false, + items: null, + }, + { + label: 'wot', + value: 'wat > wot', + count: 15, + isRefined: false, + items: null, + }, + ], + }, + { + label: 'oy', + value: 'oy', + count: 10, + isRefined: false, + items: null, + }, + ]); + }); + + it('facetValues results does not use facetOrdering if disabled', () => { + const props = { + attributes: ['lvl0', 'lvl1'], + facetOrdering: false, + contextValue, + }; + const searchState = { hierarchicalMenu: { lvl0: 'wat' } }; + const state = connect.getSearchParameters( + new SearchParameters(), + props, + searchState + ); + const results = new SearchResults(state, [ + { + hits: [], + renderingContent: { + facetOrdering: { + values: { + lvl0: { + order: ['wat'], + }, + lvl1: { + order: ['wat > wut'], + }, + }, + }, + }, + facets: { + lvl0: { + wat: 20, + oy: 10, + }, + lvl1: { + 'wat > wot': 15, + 'wat > wut': 5, + }, + }, + }, + ]); + + const providedProps = connect.getProvidedProps(props, searchState, { + results, + }); + expect(providedProps.items).toEqual([ + { + label: 'oy', + value: 'oy', + count: 10, + isRefined: false, + items: null, + }, + { + label: 'wat', + value: undefined, + count: 20, + isRefined: true, + items: [ + { + label: 'wot', + value: 'wat > wot', + count: 15, + isRefined: false, + items: null, + }, + { + label: 'wut', + value: 'wat > wut', + count: 5, + isRefined: false, + items: null, + }, + ], + }, + ]); + }); + it('shows the effect of showMoreLimit when there is no transformItems', () => { const results = { getFacetValues: jest.fn(), diff --git a/packages/react-instantsearch-core/src/connectors/__tests__/connectMenu.js b/packages/react-instantsearch-core/src/connectors/__tests__/connectMenu.js index 263e87bfd1..28925a4215 100644 --- a/packages/react-instantsearch-core/src/connectors/__tests__/connectMenu.js +++ b/packages/react-instantsearch-core/src/connectors/__tests__/connectMenu.js @@ -1,4 +1,4 @@ -import { SearchParameters } from 'algoliasearch-helper'; +import { SearchParameters, SearchResults } from 'algoliasearch-helper'; import connect from '../connectMenu'; jest.mock('../../core/createConnector', () => x => x); @@ -245,6 +245,116 @@ describe('connectMenu', () => { ]); }); + it('facetValues have facetOrdering by default', () => { + const userProps = { + ...connect.defaultProps, + attribute: 'ok', + contextValue, + }; + const searchState = { + menu: { ok: 'wat' }, + }; + const parameters = connect.getSearchParameters( + new SearchParameters(), + userProps, + searchState + ); + + const searchResults = new SearchResults(parameters, [ + { + hits: [], + renderingContent: { + facetOrdering: { + values: { + ok: { + order: ['wat'], + }, + }, + }, + }, + facets: { + ok: { + wat: 20, + lol: 2000, + }, + }, + }, + ]); + + const providedProps = connect.getProvidedProps(userProps, searchState, { + results: searchResults, + }); + + expect(providedProps.items).toEqual([ + { + count: 20, + isRefined: true, + label: 'wat', + value: '', + }, + { + count: 2000, + isRefined: false, + label: 'lol', + value: 'lol', + }, + ]); + expect(providedProps.isFromSearch).toBe(false); + }); + + it('facetValues results does not use facetOrdering if disabled', () => { + const userProps = { attribute: 'ok', facetOrdering: false, contextValue }; + const searchState = { + menu: { ok: 'wat' }, + }; + const parameters = connect.getSearchParameters( + new SearchParameters(), + userProps, + searchState + ); + + const searchResults = new SearchResults(parameters, [ + { + hits: [], + renderingContent: { + facetOrdering: { + values: { + ok: { + order: ['wat'], + }, + }, + }, + }, + facets: { + ok: { + wat: 20, + lol: 2000, + }, + }, + }, + ]); + + const providedProps = connect.getProvidedProps(userProps, searchState, { + results: searchResults, + }); + + expect(providedProps.items).toEqual([ + { + count: 2000, + isRefined: false, + label: 'lol', + value: 'lol', + }, + { + count: 20, + isRefined: true, + label: 'wat', + value: '', + }, + ]); + expect(providedProps.isFromSearch).toBe(false); + }); + it("calling refine updates the widget's search state", () => { const nextState = connect.refine( { attribute: 'ok', contextValue }, @@ -435,13 +545,14 @@ describe('connectMenu', () => { }; props = connect.getProvidedProps( - { attribute: 'ok', contextValue }, + { ...connect.defaultProps, attribute: 'ok', contextValue }, {}, { results } ); expect(results.getFacetValues).toHaveBeenCalledWith('ok', { sortBy: ['count:desc', 'name:asc'], + facetOrdering: true, }); expect(props.items).toEqual([ @@ -479,13 +590,19 @@ describe('connectMenu', () => { }; props = connect.getProvidedProps( - { attribute: 'ok', searchable: true, contextValue }, + { + ...connect.defaultProps, + attribute: 'ok', + searchable: true, + contextValue, + }, {}, { results } ); expect(results.getFacetValues).toHaveBeenCalledWith('ok', { sortBy: undefined, + facetOrdering: true, }); expect(props.items).toEqual([ diff --git a/packages/react-instantsearch-core/src/connectors/__tests__/connectRefinementList.js b/packages/react-instantsearch-core/src/connectors/__tests__/connectRefinementList.js index 21421bead3..93db3a16b0 100644 --- a/packages/react-instantsearch-core/src/connectors/__tests__/connectRefinementList.js +++ b/packages/react-instantsearch-core/src/connectors/__tests__/connectRefinementList.js @@ -1,4 +1,4 @@ -import { SearchParameters } from 'algoliasearch-helper'; +import { SearchResults, SearchParameters } from 'algoliasearch-helper'; import connect from '../connectRefinementList'; jest.mock('../../core/createConnector', () => x => x); @@ -241,6 +241,116 @@ describe('connectRefinementList', () => { expect(props.isFromSearch).toBe(true); }); + it('facetValues have facetOrdering by default', () => { + const userProps = { + ...connect.defaultProps, + attribute: 'ok', + contextValue, + }; + const searchState = { + refinementList: { ok: ['wat'] }, + }; + const parameters = connect.getSearchParameters( + new SearchParameters(), + userProps, + searchState + ); + + const searchResults = new SearchResults(parameters, [ + { + hits: [], + renderingContent: { + facetOrdering: { + values: { + ok: { + order: ['lol'], + }, + }, + }, + }, + facets: { + ok: { + wat: 20, + lol: 2000, + }, + }, + }, + ]); + + const providedProps = connect.getProvidedProps(userProps, searchState, { + results: searchResults, + }); + + expect(providedProps.items).toEqual([ + { + count: 2000, + isRefined: false, + label: 'lol', + value: ['wat', 'lol'], + }, + { + count: 20, + isRefined: true, + label: 'wat', + value: [], + }, + ]); + expect(providedProps.isFromSearch).toBe(false); + }); + + it('facetValues results does not use facetOrdering if disabled', () => { + const userProps = { attribute: 'ok', facetOrdering: false, contextValue }; + const searchState = { + refinementList: { ok: ['wat'] }, + }; + const parameters = connect.getSearchParameters( + new SearchParameters(), + userProps, + searchState + ); + + const searchResults = new SearchResults(parameters, [ + { + hits: [], + renderingContent: { + facetOrdering: { + values: { + ok: { + order: ['lol'], + }, + }, + }, + }, + facets: { + ok: { + wat: 20, + lol: 2000, + }, + }, + }, + ]); + + const providedProps = connect.getProvidedProps(userProps, searchState, { + results: searchResults, + }); + + expect(providedProps.items).toEqual([ + { + count: 20, + isRefined: true, + label: 'wat', + value: [], + }, + { + count: 2000, + isRefined: false, + label: 'lol', + value: ['wat', 'lol'], + }, + ]); + expect(providedProps.isFromSearch).toBe(false); + }); + it("calling refine updates the widget's search state", () => { const nextState = connect.refine( { attribute: 'ok', contextValue }, diff --git a/packages/react-instantsearch-core/src/connectors/connectHierarchicalMenu.js b/packages/react-instantsearch-core/src/connectors/connectHierarchicalMenu.js index 3abc77555f..65674dc68e 100644 --- a/packages/react-instantsearch-core/src/connectors/connectHierarchicalMenu.js +++ b/packages/react-instantsearch-core/src/connectors/connectHierarchicalMenu.js @@ -161,6 +161,7 @@ export default createConnector({ limit: PropTypes.number, showMoreLimit: PropTypes.number, transformItems: PropTypes.func, + facetOrdering: PropTypes.bool, }, defaultProps: { @@ -170,10 +171,11 @@ export default createConnector({ separator: ' > ', rootPath: null, showParentLevel: true, + facetOrdering: true, }, getProvidedProps(props, searchState, searchResults) { - const { showMore, limit, showMoreLimit } = props; + const { showMore, limit, showMoreLimit, facetOrdering } = props; const id = getId(props); const results = getResults(searchResults, { @@ -194,7 +196,7 @@ export default createConnector({ }; } const itemsLimit = showMore ? showMoreLimit : limit; - const value = results.getFacetValues(id, { sortBy }); + const value = results.getFacetValues(id, { sortBy, facetOrdering }); const items = value.data ? transformValue(value.data, props, searchState, { ais: props.contextValue, diff --git a/packages/react-instantsearch-core/src/connectors/connectMenu.js b/packages/react-instantsearch-core/src/connectors/connectMenu.js index 4b67d2d6ea..d3f1e7def9 100644 --- a/packages/react-instantsearch-core/src/connectors/connectMenu.js +++ b/packages/react-instantsearch-core/src/connectors/connectMenu.js @@ -82,12 +82,14 @@ export default createConnector({ defaultRefinement: PropTypes.string, transformItems: PropTypes.func, searchable: PropTypes.bool, + facetOrdering: PropTypes.bool, }, defaultProps: { showMore: false, limit: 10, showMoreLimit: 20, + facetOrdering: true, }, getProvidedProps( @@ -97,7 +99,7 @@ export default createConnector({ meta, searchForFacetValuesResults ) { - const { attribute, searchable, indexContextValue } = props; + const { attribute, searchable, indexContextValue, facetOrdering } = props; const results = getResults(searchResults, { ais: props.contextValue, multiIndexContext: props.indexContextValue, @@ -149,6 +151,7 @@ export default createConnector({ items = results .getFacetValues(attribute, { sortBy: searchable ? undefined : defaultSortBy, + facetOrdering, }) .map(v => ({ label: v.name, diff --git a/packages/react-instantsearch-core/src/connectors/connectRefinementList.js b/packages/react-instantsearch-core/src/connectors/connectRefinementList.js index 6d4159589a..99cbe1ea07 100644 --- a/packages/react-instantsearch-core/src/connectors/connectRefinementList.js +++ b/packages/react-instantsearch-core/src/connectors/connectRefinementList.js @@ -104,6 +104,7 @@ export default createConnector({ ), searchable: PropTypes.bool, transformItems: PropTypes.func, + facetOrdering: PropTypes.bool, }, defaultProps: { @@ -111,6 +112,7 @@ export default createConnector({ showMore: false, limit: 10, showMoreLimit: 20, + facetOrdering: true, }, getProvidedProps( @@ -120,7 +122,7 @@ export default createConnector({ metadata, searchForFacetValuesResults ) { - const { attribute, searchable, indexContextValue } = props; + const { attribute, searchable, indexContextValue, facetOrdering } = props; const results = getResults(searchResults, { ais: props.contextValue, multiIndexContext: props.indexContextValue, @@ -167,7 +169,7 @@ export default createConnector({ count: v.count, isRefined: v.isRefined, })) - : results.getFacetValues(attribute, { sortBy }).map(v => ({ + : results.getFacetValues(attribute, { sortBy, facetOrdering }).map(v => ({ label: v.name, value: getValue(v.name, props, searchState, { ais: props.contextValue, diff --git a/packages/react-instantsearch-core/src/core/indexUtils.js b/packages/react-instantsearch-core/src/core/indexUtils.js index f6d02837c3..e5401c572b 100644 --- a/packages/react-instantsearch-core/src/core/indexUtils.js +++ b/packages/react-instantsearch-core/src/core/indexUtils.js @@ -6,6 +6,9 @@ export function getIndexId(context) { : context.ais.mainTargetedIndex; } +/** + * @returns {import('algoliasearch-helper').SearchResults} results + */ export function getResults(searchResults, context) { if (searchResults.results) { if (searchResults.results.hits) { diff --git a/packages/react-instantsearch-dom/package.json b/packages/react-instantsearch-dom/package.json index d88a9c408c..019e5446c5 100644 --- a/packages/react-instantsearch-dom/package.json +++ b/packages/react-instantsearch-dom/package.json @@ -35,7 +35,7 @@ }, "dependencies": { "@babel/runtime": "^7.1.2", - "algoliasearch-helper": "^3.4.3", + "algoliasearch-helper": "^3.5.3", "classnames": "^2.2.5", "prop-types": "^15.6.2", "react-fast-compare": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index 8d8d612aa5..c04130357d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,43 +2,48 @@ # yarn lockfile v1 -"@algolia/cache-browser-local-storage@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.8.5.tgz#3eb10758c794d3cc8fc4e9f09e339d5b9589dc9c" - integrity sha512-9rs/Yi82ilgifweJamOy4DlJ4xPGsCN/zg+RKy4vjytNhOrkEHLRQC8vPZ3OhD8KVlw9lRQIZTlgjgFl8iMeeA== +"@algolia/cache-browser-local-storage@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.9.3.tgz#44e6306a548a76c410b5f64a8a0a1b65f63183c9" + integrity sha512-t9yKMfPNxxEUk/PPbZtXj0GCttDk1pk0wV2eA5udIOgf+Wqb/77yH75zz1u8EmCBGPe+FWXjSVT/wS1tlQz7SA== dependencies: - "@algolia/cache-common" "4.8.5" + "@algolia/cache-common" "4.9.3" "@algolia/cache-common@4.8.5": version "4.8.5" resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.8.5.tgz#86f8a6878bd2fc5c8d889e48d18d3033faa0bcd8" integrity sha512-4SvRWnagKtwBFAy8Rsfmv0/Uk53fZL+6dy2idwdx6SjMGKSs0y1Qv+thb4h/k/H5MONisAoT9C2rgZ/mqwh5yw== -"@algolia/cache-in-memory@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.8.5.tgz#13055d54775f99aa4e1ce051e73079d0f207a3e6" - integrity sha512-XBBfqs28FbjwLboY3sxvuzBgYsuXdFsj2mUvkgxfb0GVEzwW4I0NM7KzSPwT+iht55WS1PgIOnynjmhPsrubCw== +"@algolia/cache-common@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.9.3.tgz#0b3ca07c9af108433b4d3423a03511c3d053fed5" + integrity sha512-4dvzz28ESs7lRHmpBIjlmRloD9oGeD90E2C0QWNQYuAYosSdXGwW7vw4vdGRdPoL32t6u6S+47Bk6Dhcbw2ftA== + +"@algolia/cache-in-memory@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.9.3.tgz#0bae2ad1de6537ca28efaf5280051265903bfca5" + integrity sha512-e1eRpP/Ht9qmLw5Sp674N6Y0c59K0L2LBI71EBOlq1j+kVc+JxVO03he5g+nQ7JOwLijyJPrkbm3RvXb5CX0sA== dependencies: - "@algolia/cache-common" "4.8.5" + "@algolia/cache-common" "4.9.3" -"@algolia/client-account@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.8.5.tgz#92df1dd0a7bea06e329873c7098c72cc4dd8e9d6" - integrity sha512-DjXMpeCdY4J4IDBfowiG6Xl9ec/FhG1NpPQM0Uv4xXsc/TeeZ1JgbgNDhWe9jW0jBEALy+a/RmPrZ0vsxcadsg== +"@algolia/client-account@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.9.3.tgz#af9bf3612d05e87aa36372da50a2f0a9265de201" + integrity sha512-mSF0jiAo/tWKf/Z7mqhz6ETltrl+L+Zt2xuM3W5y1UOZvj47fn2ZcMRce8MQ+dd54t9iA8qIa+0XGlCSQf9lxA== dependencies: - "@algolia/client-common" "4.8.5" - "@algolia/client-search" "4.8.5" - "@algolia/transporter" "4.8.5" + "@algolia/client-common" "4.9.3" + "@algolia/client-search" "4.9.3" + "@algolia/transporter" "4.9.3" -"@algolia/client-analytics@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.8.5.tgz#1aa731a146b347022a0a9e0eb009f2b2f8d9825f" - integrity sha512-PQEY+chbHmZnRJdaWsvUYzDpEPr60az0EPUexdouvXGZId15/SnDaXjnf89F7tYmCzkHdUtG4bSvPzAupQ4AFA== +"@algolia/client-analytics@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.9.3.tgz#cddb4a97d796291d91bd15735de008b2d80a0b1b" + integrity sha512-Z3EjegxsdTMRmOLoDBnCZJjdL3ZM4J/G7TMe2PIArdCJFWM4iDnO7/MvYasqpK0PPOCHRh0wS4yKG9rZOz6Vsw== dependencies: - "@algolia/client-common" "4.8.5" - "@algolia/client-search" "4.8.5" - "@algolia/requester-common" "4.8.5" - "@algolia/transporter" "4.8.5" + "@algolia/client-common" "4.9.3" + "@algolia/client-search" "4.9.3" + "@algolia/requester-common" "4.9.3" + "@algolia/transporter" "4.9.3" "@algolia/client-common@4.8.5": version "4.8.5" @@ -48,14 +53,22 @@ "@algolia/requester-common" "4.8.5" "@algolia/transporter" "4.8.5" -"@algolia/client-recommendation@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/client-recommendation/-/client-recommendation-4.8.5.tgz#f02f8f8ff3983597cae677ec0bc3eb01ae26121a" - integrity sha512-ffawCC1C25rCa8/JU2niRZgwr8aV9b2qsLVMo73GXFzi2lceXPAe9K68mt/BGHU+w7PFUwVHsV2VmB+G/HQRVw== +"@algolia/client-common@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.9.3.tgz#167a6863b55ffe7788ab9ac98b1b6fd0078f79df" + integrity sha512-6GAfuNqMrBN3094H0DzvQyxJoKUkyQpEr5OiFhH8I3lihI1rTtjEUrNDTsVp6e9VsR2OCRpnL9EEDv2HcGe8cw== dependencies: - "@algolia/client-common" "4.8.5" - "@algolia/requester-common" "4.8.5" - "@algolia/transporter" "4.8.5" + "@algolia/requester-common" "4.9.3" + "@algolia/transporter" "4.9.3" + +"@algolia/client-recommendation@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/client-recommendation/-/client-recommendation-4.9.3.tgz#e2031237b2904c9d9b946fc846c87a21ad67bc5a" + integrity sha512-r+MNluwnUTr1tgHWQ5BPRw0A0YJZp9sXjSVxPCY3a+N6BgLaX4E02+FA8VrqVs8uR7mMQSLaJHoeCKnmNPrk9w== + dependencies: + "@algolia/client-common" "4.9.3" + "@algolia/requester-common" "4.9.3" + "@algolia/transporter" "4.9.3" "@algolia/client-search@4.8.5": version "4.8.5" @@ -66,36 +79,55 @@ "@algolia/requester-common" "4.8.5" "@algolia/transporter" "4.8.5" +"@algolia/client-search@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.9.3.tgz#6259645ad5a7e7388727343806bcf2d0cf3e343a" + integrity sha512-8C6woYf6bY4Fh9H9nKY5IDDeBPwQ3nZn9QMQdgUj9ffDU8UzPqSivtLER1A+I81p1j9h+aBADRifwzIYtSXOkA== + dependencies: + "@algolia/client-common" "4.9.3" + "@algolia/requester-common" "4.9.3" + "@algolia/transporter" "4.9.3" + "@algolia/logger-common@4.8.5": version "4.8.5" resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.8.5.tgz#ef275c532c21424f4b29b26ec2e27de2c973ad95" integrity sha512-PS6NS6bpED0rAxgCPGhjZJg9why0PnoVEE7ZoCbPq6lsAOc6FPlQLri4OiLyU7wx8RWDoVtOadyzulqAAsfPSQ== -"@algolia/logger-console@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.8.5.tgz#8fe547fdcf76574963503f7c4ff2673e792ae886" - integrity sha512-3+4gLSbwzuGmrb5go3IZNcFIYVMSbB4c8UMtWEJ/gDBtgGZIvT6f/KlvVSOHIhthSxaM3Y13V6Qile/SpGqc6A== +"@algolia/logger-common@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.9.3.tgz#d9b976524313b11f11c6ec546e2ed451c7964a11" + integrity sha512-8hGQ5HQvjx2kr7GWOmpON1tcRX2+VHqVg4p+qJqCBsPFlXbAshUyRJkxuen20eem2EAA5Cmmo1fPy/jlqdMMHA== + +"@algolia/logger-console@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.9.3.tgz#f690bf8d5262a82425da26b42a519d7ec6c3784a" + integrity sha512-7FGulrAjS/oCVRShKJw5qFuyHOZk/44jolEtNtXvO/tZRR8hPPiow16Vrd3ByRSIhghkC5zj6at4nQhoPK+KqA== dependencies: - "@algolia/logger-common" "4.8.5" + "@algolia/logger-common" "4.9.3" -"@algolia/requester-browser-xhr@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.8.5.tgz#95e01e2dca38358055f08440f46d4f0b9f735280" - integrity sha512-M/Gf2vv/fU4+CqDW+wok7HPpEcLym3NtDzU9zaPzGYI/9X7o36581oyfnzt2pNfsXSQVj5a2pZVUWC3Z4SO27w== +"@algolia/requester-browser-xhr@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.9.3.tgz#1c0fd594e253b41786b3408ade9f63862fe0c577" + integrity sha512-hP4YgxcY1kol0d+joXpO4BJuXjgF+vy3eBPk8WCXvZucv8hl5Vqb4BLccDMck+sTqP4Tqglwh/KwVTQrpmi/wA== dependencies: - "@algolia/requester-common" "4.8.5" + "@algolia/requester-common" "4.9.3" "@algolia/requester-common@4.8.5": version "4.8.5" resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.8.5.tgz#952dec3b36c14495af158914cd6c0e2c9ce72b5e" integrity sha512-OIhsdwIrJVAlVlP7cwlt+RoR5AmxAoTGrFokOY9imVmgqXUUljdKO/DjhRL8vwYGFEidZ9efIjAIQ2B3XOhT9A== -"@algolia/requester-node-http@4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.8.5.tgz#a1e5a6d23a9a4e78abd5a2416f1a6c232b0a7e14" - integrity sha512-viHAjfo53A3VSE7Bb/nzgpSMZ3prPp2qti7Wg8w7qxhntppKp3Fln6t4Vp+BoPOqruLsj139xXhheAKeRcYa0w== +"@algolia/requester-common@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.9.3.tgz#58fb72ca3f4f7714d75287ff568000ee6c2afac6" + integrity sha512-AgUw1iA/JkanZC+dhkSLyeiVgBhaaM3bI20f3cokuuDdz4X6F+hzi0vEpUZrEuNfnMLbUg8gxq3Vcg1/L9+9MA== + +"@algolia/requester-node-http@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.9.3.tgz#a2bf0e7048fe3b81c6b6b170f8f68a5789dadafe" + integrity sha512-+nz7rRnI9qNcdZjHpyAyvcDLAO9mGobqsAi0aicxMka/szU1HVUX6+pvSOiiOsD8ST3R13rJuufgHfWdDUysQg== dependencies: - "@algolia/requester-common" "4.8.5" + "@algolia/requester-common" "4.9.3" "@algolia/transporter@4.8.5": version "4.8.5" @@ -106,6 +138,15 @@ "@algolia/logger-common" "4.8.5" "@algolia/requester-common" "4.8.5" +"@algolia/transporter@4.9.3": + version "4.9.3" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.9.3.tgz#5a0933d4e59acdf88712156b2ab6f1b46c0a7f88" + integrity sha512-oJ68VSSpmUyB9EByqoyx25wgcrO9fgXtjH+pOtKoKmCW+RfxHW5agltJoQ808N8uq/AvP5ugMkRLGL3xf4WdzQ== + dependencies: + "@algolia/cache-common" "4.9.3" + "@algolia/logger-common" "4.9.3" + "@algolia/requester-common" "4.9.3" + "@babel/cli@7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.4.4.tgz#5454bb7112f29026a4069d8e6f0e1794e651966c" @@ -4809,25 +4850,32 @@ algoliasearch-helper@^3.4.3: dependencies: events "^1.1.1" -algoliasearch@4.8.5: - version "4.8.5" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.8.5.tgz#17a97b01c46c1ac5c1cd99d950d65e7064c8b8a9" - integrity sha512-GjKjpeevpePEJYinGokASNtIkl1t5EseNMlqDNAc+sXE8+iyyeqTyiJsN7bwlRG2BIremuslE/NlwdEfUuBLJw== +algoliasearch-helper@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.5.3.tgz#fbf8b328bc103efdefde59a7d25eaffe85b2490f" + integrity sha512-DtSlOKAJ6TGkQD6u58g6/ABdMmHf3pAj6xVL5hJF+D4z9ldDRf/f5v6puNIxGOlJRwGVvFGyz34beYNqhLDUbQ== dependencies: - "@algolia/cache-browser-local-storage" "4.8.5" - "@algolia/cache-common" "4.8.5" - "@algolia/cache-in-memory" "4.8.5" - "@algolia/client-account" "4.8.5" - "@algolia/client-analytics" "4.8.5" - "@algolia/client-common" "4.8.5" - "@algolia/client-recommendation" "4.8.5" - "@algolia/client-search" "4.8.5" - "@algolia/logger-common" "4.8.5" - "@algolia/logger-console" "4.8.5" - "@algolia/requester-browser-xhr" "4.8.5" - "@algolia/requester-common" "4.8.5" - "@algolia/requester-node-http" "4.8.5" - "@algolia/transporter" "4.8.5" + events "^1.1.1" + +algoliasearch@4.9.3: + version "4.9.3" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.9.3.tgz#b22ef0ae0450304cdf5264369a29cefa71ea2b30" + integrity sha512-VLl9pYXhVB397xTW369sy13qw3m1hHzCfj9zSdeDDYVwTxHiiok/QvhPKAMIzjqyUoY07O8j+941UxYZjugsMQ== + dependencies: + "@algolia/cache-browser-local-storage" "4.9.3" + "@algolia/cache-common" "4.9.3" + "@algolia/cache-in-memory" "4.9.3" + "@algolia/client-account" "4.9.3" + "@algolia/client-analytics" "4.9.3" + "@algolia/client-common" "4.9.3" + "@algolia/client-recommendation" "4.9.3" + "@algolia/client-search" "4.9.3" + "@algolia/logger-common" "4.9.3" + "@algolia/logger-console" "4.9.3" + "@algolia/requester-browser-xhr" "4.9.3" + "@algolia/requester-common" "4.9.3" + "@algolia/requester-node-http" "4.9.3" + "@algolia/transporter" "4.9.3" "algoliasearch@>= 3.27.1 < 5": version "3.35.1"