@zengenti/contensis-react-base 4.0.0-beta.8 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +14 -1
  2. package/cjs/{App-vZrUfVgQ.js → App-CNylISW7.js} +546 -104
  3. package/cjs/App-CNylISW7.js.map +1 -0
  4. package/cjs/{ChangePassword.container-ECjEXixF.js → ChangePassword.container-C4Du3Wb1.js} +57 -50
  5. package/cjs/ChangePassword.container-C4Du3Wb1.js.map +1 -0
  6. package/cjs/{SSRContext-DVj_QAC1.js → ContensisDeliveryApi-MfcvdfDR.js} +32 -74
  7. package/cjs/ContensisDeliveryApi-MfcvdfDR.js.map +1 -0
  8. package/cjs/CookieConstants-DfPiWCRZ.js +12 -0
  9. package/cjs/CookieConstants-DfPiWCRZ.js.map +1 -0
  10. package/{esm/CookieHelper.class-FTURFpz3.js → cjs/CookieHelper.class-Det3qfdU.js} +4 -6
  11. package/cjs/CookieHelper.class-Det3qfdU.js.map +1 -0
  12. package/cjs/{RouteLoader-D5Yg7EB5.js → RouteLoader-DJeM8cym.js} +17 -9
  13. package/cjs/RouteLoader-DJeM8cym.js.map +1 -0
  14. package/cjs/SSRContext-tMufQDHY.js +116 -0
  15. package/cjs/SSRContext-tMufQDHY.js.map +1 -0
  16. package/cjs/ToJs-BsWqWjdm.js +23 -0
  17. package/cjs/ToJs-BsWqWjdm.js.map +1 -0
  18. package/cjs/{VersionInfo-B_dKCubg.js → VersionInfo-zFPsvS8q.js} +3 -25
  19. package/cjs/VersionInfo-zFPsvS8q.js.map +1 -0
  20. package/cjs/client.js +63 -65
  21. package/cjs/client.js.map +1 -1
  22. package/cjs/contensis-react-base.js +223 -132
  23. package/cjs/contensis-react-base.js.map +1 -1
  24. package/cjs/i18n.js +75 -0
  25. package/cjs/i18n.js.map +1 -0
  26. package/cjs/{ToJs-C9jwV7YB.js → matchGroups-dqONU-vY.js} +2 -22
  27. package/cjs/matchGroups-dqONU-vY.js.map +1 -0
  28. package/cjs/redux.js +8 -6
  29. package/cjs/redux.js.map +1 -1
  30. package/cjs/routing.js +15 -7
  31. package/cjs/routing.js.map +1 -1
  32. package/cjs/{sagas-CbZhaRNd.js → sagas-BCy9u6zA.js} +523 -370
  33. package/cjs/sagas-BCy9u6zA.js.map +1 -0
  34. package/cjs/search.js +54 -29
  35. package/cjs/search.js.map +1 -1
  36. package/cjs/{selectors-wCs5fHD4.js → selectors-BrxJ8-F8.js} +27 -6
  37. package/cjs/selectors-BrxJ8-F8.js.map +1 -0
  38. package/cjs/selectors-DAQR0uZa.js +18 -0
  39. package/cjs/selectors-DAQR0uZa.js.map +1 -0
  40. package/cjs/slice-5xJMH24n.js +69 -0
  41. package/cjs/slice-5xJMH24n.js.map +1 -0
  42. package/cjs/{store-D07FOXvM.js → store-B7SJs5Hf.js} +64 -5
  43. package/cjs/store-B7SJs5Hf.js.map +1 -0
  44. package/cjs/urls-DGZlAs0y.js +25 -0
  45. package/cjs/urls-DGZlAs0y.js.map +1 -0
  46. package/cjs/user.js +20 -17
  47. package/cjs/user.js.map +1 -1
  48. package/cjs/util-eOjxDjxF.js +148 -0
  49. package/cjs/util-eOjxDjxF.js.map +1 -0
  50. package/cjs/util.js +80 -22
  51. package/cjs/util.js.map +1 -1
  52. package/cjs/{version-CM-bJ62L.js → version-rFG9Y6_B.js} +2 -2
  53. package/cjs/{version-CM-bJ62L.js.map → version-rFG9Y6_B.js.map} +1 -1
  54. package/cjs/{version-B7XFkBhY.js → version-yjHMrfVz.js} +15 -16
  55. package/cjs/version-yjHMrfVz.js.map +1 -0
  56. package/esm/{App-DLZweVSp.js → App-Bvs7Km54.js} +507 -66
  57. package/esm/App-Bvs7Km54.js.map +1 -0
  58. package/esm/{ChangePassword.container-BgzIy8dA.js → ChangePassword.container-CUBtn82K.js} +19 -13
  59. package/esm/ChangePassword.container-CUBtn82K.js.map +1 -0
  60. package/esm/{SSRContext-BE8ElZ3X.js → ContensisDeliveryApi-LWYXevZ1.js} +30 -67
  61. package/esm/ContensisDeliveryApi-LWYXevZ1.js.map +1 -0
  62. package/esm/CookieConstants-DEmbwzYr.js +7 -0
  63. package/esm/CookieConstants-DEmbwzYr.js.map +1 -0
  64. package/{cjs/CookieHelper.class-C3Eqoze9.js → esm/CookieHelper.class-C6rTRl_1.js} +2 -14
  65. package/esm/CookieHelper.class-C6rTRl_1.js.map +1 -0
  66. package/esm/{RouteLoader-xeQBXywk.js → RouteLoader-CzrlySZf.js} +14 -6
  67. package/esm/RouteLoader-CzrlySZf.js.map +1 -0
  68. package/esm/SSRContext-Bxtg1KGv.js +106 -0
  69. package/esm/SSRContext-Bxtg1KGv.js.map +1 -0
  70. package/esm/ToJs-BnRRHk6f.js +17 -0
  71. package/esm/ToJs-BnRRHk6f.js.map +1 -0
  72. package/esm/{VersionInfo-Cno7K0OA.js → VersionInfo-By2ZCZOh.js} +4 -24
  73. package/esm/VersionInfo-By2ZCZOh.js.map +1 -0
  74. package/esm/client.js +63 -64
  75. package/esm/client.js.map +1 -1
  76. package/esm/contensis-react-base.js +216 -127
  77. package/esm/contensis-react-base.js.map +1 -1
  78. package/esm/i18n.js +64 -0
  79. package/esm/i18n.js.map +1 -0
  80. package/esm/{ToJs-CNzfvyxJ.js → matchGroups-_w8BwzCC.js} +3 -18
  81. package/esm/matchGroups-_w8BwzCC.js.map +1 -0
  82. package/esm/redux.js +11 -8
  83. package/esm/redux.js.map +1 -1
  84. package/esm/routing.js +14 -7
  85. package/esm/routing.js.map +1 -1
  86. package/esm/{sagas-xJU-zOpn.js → sagas-Fr9yRduO.js} +511 -357
  87. package/esm/sagas-Fr9yRduO.js.map +1 -0
  88. package/esm/search.js +73 -47
  89. package/esm/search.js.map +1 -1
  90. package/esm/{selectors-DO2ocdOp.js → selectors-8ROQrTd7.js} +25 -7
  91. package/esm/selectors-8ROQrTd7.js.map +1 -0
  92. package/esm/selectors-DcmvOeX2.js +10 -0
  93. package/esm/selectors-DcmvOeX2.js.map +1 -0
  94. package/esm/slice-C6JLQik8.js +63 -0
  95. package/esm/slice-C6JLQik8.js.map +1 -0
  96. package/esm/{store-3u0RzHZ0.js → store-B4IrBYHm.js} +64 -6
  97. package/esm/store-B4IrBYHm.js.map +1 -0
  98. package/esm/urls-tLxo_skx.js +22 -0
  99. package/esm/urls-tLxo_skx.js.map +1 -0
  100. package/esm/user.js +9 -6
  101. package/esm/user.js.map +1 -1
  102. package/esm/util-Bl2u6LpY.js +136 -0
  103. package/esm/util-Bl2u6LpY.js.map +1 -0
  104. package/esm/util.js +58 -14
  105. package/esm/util.js.map +1 -1
  106. package/esm/{version-wnf-TITV.js → version-BQAL8sQO.js} +2 -2
  107. package/esm/{version-wnf-TITV.js.map → version-BQAL8sQO.js.map} +1 -1
  108. package/esm/{version-BlsI7hX2.js → version-CA9Mdm3A.js} +16 -16
  109. package/esm/version-CA9Mdm3A.js.map +1 -0
  110. package/i18n/package.json +5 -0
  111. package/models/app/pages/VersionInfo/components/VersionInfo.d.ts +1 -1
  112. package/models/app/pages/VersionInfo/components/VersionInfo.styled.d.ts +1 -2
  113. package/models/i18n/index.d.ts +5 -0
  114. package/models/i18n/redux/sagas.d.ts +19 -0
  115. package/models/i18n/redux/selectors.d.ts +11 -0
  116. package/models/i18n/redux/slice.d.ts +198 -0
  117. package/models/i18n/routes.d.ts +8 -0
  118. package/models/i18n/useI18n.hook.d.ts +20 -0
  119. package/models/index.d.ts +1 -0
  120. package/models/models/AppState.d.ts +2 -0
  121. package/models/models/ContentTypeMapping.d.ts +6 -1
  122. package/models/models/EntryMapper.d.ts +2 -1
  123. package/models/models/Locales.d.ts +11 -0
  124. package/models/models/MatchedRoute.d.ts +5 -1
  125. package/models/models/RouteComponent.d.ts +0 -1
  126. package/models/models/RouteNode.d.ts +4 -2
  127. package/models/models/SSRContext.d.ts +4 -4
  128. package/models/models/StaticRoute.d.ts +12 -1
  129. package/models/models/WithEvents.d.ts +8 -0
  130. package/models/models/config/AppConfig.d.ts +2 -0
  131. package/models/models/config/I18n.d.ts +38 -0
  132. package/models/models/config/ServerConfig.d.ts +14 -0
  133. package/models/redux/index.d.ts +2 -1
  134. package/models/redux/sagas/index.d.ts +3 -1
  135. package/models/redux/sagas/injector.d.ts +13 -0
  136. package/models/redux/store/injectors/index.d.ts +26 -0
  137. package/models/redux/store/injectors/inject.d.ts +24 -0
  138. package/models/redux/store/injectors/util.d.ts +2 -0
  139. package/models/redux/store/store.d.ts +13 -4
  140. package/models/redux/util.d.ts +1 -1
  141. package/models/routing/components/RouteLoader.d.ts +3 -3
  142. package/models/routing/httpContext.d.ts +0 -1
  143. package/models/routing/index.d.ts +1 -0
  144. package/models/routing/redux/actions.d.ts +1 -1
  145. package/models/routing/redux/invokeSearch.d.ts +22 -0
  146. package/models/routing/redux/selectors.d.ts +47 -4
  147. package/models/routing/util/expressions.d.ts +1 -1
  148. package/models/routing/util/find-contenttype-mapping.d.ts +3 -1
  149. package/models/search/containers/withListing.d.ts +1 -1
  150. package/models/search/containers/withSearch.d.ts +1 -1
  151. package/models/search/models/Queries.d.ts +3 -5
  152. package/models/search/models/Search.d.ts +43 -13
  153. package/models/search/models/SearchActions.d.ts +61 -18
  154. package/models/search/models/SearchProps.d.ts +11 -10
  155. package/models/search/models/SearchState.d.ts +23 -2
  156. package/models/search/models/SearchUtil.d.ts +3 -3
  157. package/models/search/redux/getIn.d.ts +2 -2
  158. package/models/search/redux/reducers.d.ts +3 -4
  159. package/models/search/redux/sagas.d.ts +13 -14
  160. package/models/search/redux/schema.d.ts +3 -3
  161. package/models/search/redux/selectors.d.ts +64 -42
  162. package/models/search/redux/util.d.ts +10 -1
  163. package/models/search/search/ContensisDeliveryApi.d.ts +6 -26
  164. package/models/search/search/expressions.d.ts +6 -4
  165. package/models/search/search/util.d.ts +9 -7
  166. package/models/search/transformations/state-to-queryparams.mapper.d.ts +1 -1
  167. package/models/server/features/linkdepth-api/search.d.ts +1 -1
  168. package/models/server/features/response-handler/render-stream.d.ts +2 -4
  169. package/models/server/features/static-assets/index.d.ts +4 -3
  170. package/models/server/internalServer.d.ts +1 -2
  171. package/models/server/middleware/subsiteDebug.d.ts +11 -0
  172. package/models/server/root.d.ts +3 -0
  173. package/models/server/util/bundles.d.ts +9 -9
  174. package/models/server/util/jsx.d.ts +2 -14
  175. package/models/user/components.styled/Login.styled.d.ts +1 -1
  176. package/models/user/components.styled/LoginForm.styled.d.ts +1 -1
  177. package/models/user/hocs/withRegistration.d.ts +1 -1
  178. package/models/util/CachedDeliveryApi.d.ts +8 -2
  179. package/models/util/ContensisDeliveryApi.d.ts +2 -4
  180. package/models/util/NoSSR.d.ts +6 -0
  181. package/models/util/SSRContext.d.ts +3 -19
  182. package/models/util/donotuse_useHistory.d.ts +6 -0
  183. package/models/util/errors.d.ts +16 -0
  184. package/models/util/index.d.ts +7 -2
  185. package/models/util/subsite.d.ts +12 -0
  186. package/models/util/urls.d.ts +1 -2
  187. package/models/util/useIsClient.d.ts +6 -0
  188. package/package.json +37 -39
  189. package/cjs/App-vZrUfVgQ.js.map +0 -1
  190. package/cjs/ChangePassword.container-ECjEXixF.js.map +0 -1
  191. package/cjs/CookieHelper.class-C3Eqoze9.js.map +0 -1
  192. package/cjs/RouteLoader-D5Yg7EB5.js.map +0 -1
  193. package/cjs/SSRContext-DVj_QAC1.js.map +0 -1
  194. package/cjs/ToJs-C9jwV7YB.js.map +0 -1
  195. package/cjs/VersionInfo-B_dKCubg.js.map +0 -1
  196. package/cjs/sagas-CbZhaRNd.js.map +0 -1
  197. package/cjs/selectors-wCs5fHD4.js.map +0 -1
  198. package/cjs/store-D07FOXvM.js.map +0 -1
  199. package/cjs/version-B7XFkBhY.js.map +0 -1
  200. package/esm/App-DLZweVSp.js.map +0 -1
  201. package/esm/ChangePassword.container-BgzIy8dA.js.map +0 -1
  202. package/esm/CookieHelper.class-FTURFpz3.js.map +0 -1
  203. package/esm/RouteLoader-xeQBXywk.js.map +0 -1
  204. package/esm/SSRContext-BE8ElZ3X.js.map +0 -1
  205. package/esm/ToJs-CNzfvyxJ.js.map +0 -1
  206. package/esm/VersionInfo-Cno7K0OA.js.map +0 -1
  207. package/esm/sagas-xJU-zOpn.js.map +0 -1
  208. package/esm/selectors-DO2ocdOp.js.map +0 -1
  209. package/esm/store-3u0RzHZ0.js.map +0 -1
  210. package/esm/version-BlsI7hX2.js.map +0 -1
  211. package/models/redux/store/injectors.d.ts +0 -31
  212. package/models/search/search/ToJs.d.ts +0 -4
@@ -3,11 +3,17 @@ import { useDispatch, useSelector } from 'react-redux';
3
3
  import { createSelector } from 'reselect';
4
4
  import * as log from 'loglevel';
5
5
  import { takeEvery, select, put, call, all } from '@redux-saga/core/effects';
6
+ import { s as selectVersionStatus } from './version-BQAL8sQO.js';
7
+ import { L as LruCache, g as getClientConfig, c as cachedSearch } from './ContensisDeliveryApi-LWYXevZ1.js';
6
8
  import { Client } from 'contensis-delivery-api';
7
- import { stringify, parse } from 'query-string';
9
+ import { a as removeEmptyAttributes, e as extractQuotedPhrases, f as fixFreeTextForElastic, c as convertKeyForAggregation, g as getItemsFromResult, b as cleanseFieldIdForAggregation, d as areArraysEqualSets, h as callCustomApi, i as timedSearch } from './util-Bl2u6LpY.js';
10
+ import { s as selectCurrentLanguage } from './selectors-DcmvOeX2.js';
11
+ import './slice-C6JLQik8.js';
8
12
  import mapJson, { jpath } from 'jsonpath-mapper';
9
13
  import { Op, OrderBy, Query } from 'contensis-core-api';
10
14
  import merge from 'deepmerge';
15
+ import { parse, stringify } from 'query-string';
16
+ import { N as selectStaticRoute, o as selectCurrentPath, f as selectCurrentProject } from './selectors-8ROQrTd7.js';
11
17
  import { c as commonjsGlobal, g as getDefaultExportFromCjs } from './_commonjsHelpers-BFTU3MAI.js';
12
18
 
13
19
  const ACTION_PREFIX = '@SEARCH/';
@@ -109,10 +115,12 @@ const navigate = (path, state) => {
109
115
  state
110
116
  };
111
117
  };
112
- const clearFilters$1 = filterKey => {
118
+ const clearFilters$1 = filterKeyOrOptions => {
113
119
  return {
114
120
  type: CLEAR_FILTERS,
115
- filterKey
121
+ clear: typeof filterKeyOrOptions === 'string' ? {
122
+ keys: [filterKeyOrOptions]
123
+ } : filterKeyOrOptions
116
124
  };
117
125
  };
118
126
  const updatePageIndex$1 = (pageIndex, scrollToElement) => {
@@ -213,12 +221,67 @@ const getImmutableOrJS = (state, stateKey, fallbackValue, returnType = globalThi
213
221
  };
214
222
 
215
223
  const getSearchContext = state => getImmutableOrJS(state, ['search', 'context'], Context.facets);
216
- const getCurrent$2 = (state, context = Context.facets) => context === Context.facets ? getCurrentFacet(state) : getCurrentListing(state);
224
+ const getCurrent$2 = (state, context = getSearchContext(state)) => context === Context.facets ? getCurrentFacet(state) : getCurrentListing(state);
217
225
  const getCurrentFacet = state => getImmutableOrJS(state, ['search', 'currentFacet']);
218
226
  const getCurrentListing = state => getImmutableOrJS(state, ['search', 'currentListing']);
219
227
  const getCurrentTab$1 = state => getImmutableOrJS(state, ['search', Context.facets, getCurrentFacet(state), 'tabId'], 0);
228
+ const getCurrentComposition = state => getImmutableOrJS(state, ['search', 'currentComposition']);
229
+
230
+ /** A localised version of `getCurrent` selector */
231
+ const getLocalisedCurrent$2 = (state, language = selectCurrentLanguage(state), context = getSearchContext(state)) => {
232
+ var _facet$i18n;
233
+ const currentFacet = getCurrent$2(state, context);
234
+ const facet = getFacet$1(state, currentFacet, context, 'js');
235
+ const i18n = (_facet$i18n = facet.i18n) === null || _facet$i18n === void 0 ? void 0 : _facet$i18n[language];
236
+ return i18n || currentFacet;
237
+ };
238
+ const getLocalisedFacetKey = (state, facet = getCurrent$2(state), language = selectCurrentLanguage(state), context = getSearchContext(state)) => {
239
+ var _getFacet;
240
+ return (_getFacet = getFacet$1(state, facet, context, 'js')) === null || _getFacet === void 0 || (_getFacet = _getFacet.i18n) === null || _getFacet === void 0 ? void 0 : _getFacet[language];
241
+ };
242
+ const getCurrentFromLocalised = (state, alias, language, context = getSearchContext(state)) => {
243
+ var _state$search;
244
+ const facets = ((_state$search = state.search) === null || _state$search === void 0 ? void 0 : _state$search[context]) || {};
245
+ for (const [facetKey, facet] of Object.entries(facets)) {
246
+ if (language) {
247
+ var _facet$i18n2;
248
+ const languageAlias = (_facet$i18n2 = facet.i18n) === null || _facet$i18n2 === void 0 ? void 0 : _facet$i18n2[language];
249
+ if (languageAlias === alias) {
250
+ return {
251
+ facet: facetKey,
252
+ language
253
+ };
254
+ }
255
+ } else {
256
+ // Fallback to check for any language
257
+ for (const lang in facet.i18n) {
258
+ if (facet.i18n[lang] === alias) {
259
+ return {
260
+ facet: facetKey,
261
+ language: lang
262
+ };
263
+ }
264
+ }
265
+ }
266
+ }
267
+ return null;
268
+ // // Default to returning the inputs
269
+ // return { facet: alias, language };
270
+ };
220
271
  const getFacets = (state, returnType) => getImmutableOrJS(state, ['search', Context.facets], {}, returnType);
221
272
  const getTabFacets$1 = state => Object.fromEntries(Object.entries(getFacets(state, 'js')).filter(([key]) => getImmutableOrJS(getFacets(state), [key, 'tabId'], 0) === getCurrentTab$1(state)));
273
+ const getCompositionFacets = (state, composition) => {
274
+ const currentComposition = composition || getCurrentComposition(state);
275
+ if (!currentComposition) return {};
276
+ const compositionConfig = getSearchCompositions(state)[currentComposition];
277
+ const context = getSearchContext(state);
278
+ if (!compositionConfig[context]) return {};
279
+ const facets = {};
280
+ for (const facet of compositionConfig[context]) {
281
+ facets[facet] = getFacet$1(state, facet, context);
282
+ }
283
+ return facets;
284
+ };
222
285
  const getFacetTitles$1 = state => Object.entries(getFacets(state, 'js')).map(([key, facet = {}]) => {
223
286
  var _facet$pagingInfo;
224
287
  return {
@@ -236,9 +299,42 @@ const getListing$1 = (state, listing = '') => {
236
299
  const currentListing = listing || getCurrentListing(state);
237
300
  return getImmutableOrJS(state, ['search', Context.listings, currentListing], {});
238
301
  };
302
+ const getComposition = (state, composition = '') => {
303
+ const currentComposition = composition || getCurrentComposition(state);
304
+ const context = getSearchContext(state);
305
+ const compositionConfig = getSearchCompositions(state)[currentComposition];
306
+ if (!compositionConfig) return {};
307
+ const facets = getCompositionFacets(state, currentComposition);
308
+ return {
309
+ ...compositionConfig,
310
+ [context]: facets
311
+ };
312
+ };
313
+
314
+ /** Return filter state for the current (or provided) facet */
239
315
  const getFilters = (state, facet, context = Context.facets, returnType) => {
240
316
  return getImmutableOrJS(state, ['search', context, facet || getCurrent$2(state, context), 'filters'], {}, returnType);
241
317
  };
318
+ const getLocalisedFilterKey = (state, key, language = selectCurrentLanguage(state), facet, context = getSearchContext(state)) => {
319
+ var _filter$i18n;
320
+ const filter = getFilters(state, facet, context, 'js')[key];
321
+ if (filter !== null && filter !== void 0 && (_filter$i18n = filter.i18n) !== null && _filter$i18n !== void 0 && _filter$i18n[language]) {
322
+ return filter.i18n[language];
323
+ }
324
+ return key;
325
+ };
326
+ const getFilterKeyFromLocalised = (state, key, language = selectCurrentLanguage(state), facet, context = getSearchContext(state)) => {
327
+ const filters = getFilters(state, facet, context, 'js');
328
+ for (const [filterKey, filter] of Object.entries(filters)) {
329
+ var _filter$i18n2;
330
+ if (((_filter$i18n2 = filter.i18n) === null || _filter$i18n2 === void 0 ? void 0 : _filter$i18n2[language]) === key) {
331
+ return filterKey;
332
+ }
333
+ }
334
+ return key;
335
+ };
336
+
337
+ /** Return filter state for the current (or provided) facet, excluding filters configured as `renderable: false` */
242
338
  const getRenderableFilters$2 = (state, facet = '', context = Context.facets) => Object.fromEntries(Object.entries(getFilters(state, facet, context, 'js')).filter(([, f = {}]) => typeof f.renderable !== 'boolean' ? true : f.renderable));
243
339
  const getFiltersToLoad = (state, facet, context = Context.facets, returnType) => {
244
340
  const filters = getFilters(state, facet, context, returnType);
@@ -249,19 +345,62 @@ const getFiltersToLoad = (state, facet, context = Context.facets, returnType) =>
249
345
  return loadedFilters.map(([filterKey, isLoaded]) => !isLoaded ? filterKey : null).filter(f => !!f);
250
346
  };
251
347
 
252
- // We lowercase the filter key unless it's an ISO date string where the T must be uppercase
253
- const getSelectedFilters = (state, facet = '', context = Context.facets, returnType) => {
254
- const filters = getFilters(state, facet, context, 'js');
348
+ /** Iterate the selected filters and update their keys to their localized equivalents */
349
+ const localiseSelectedFilterKeys = (selectedFilters, state) => {
350
+ const language = selectCurrentLanguage(state);
351
+ const filters = getFilters(state, getCurrentFacet(state), getSearchContext(state), 'js');
352
+ const localisedSelectedFilters = {};
353
+ for (const [filterKey, selectedValues] of Object.entries(selectedFilters)) {
354
+ var _filter$i18n3;
355
+ const filter = filters[filterKey];
356
+ if (filter !== null && filter !== void 0 && (_filter$i18n3 = filter.i18n) !== null && _filter$i18n3 !== void 0 && _filter$i18n3[language]) {
357
+ const localisedKey = filter.i18n[language];
358
+ localisedSelectedFilters[localisedKey] = selectedValues;
359
+ } else {
360
+ localisedSelectedFilters[filterKey] = selectedValues;
361
+ }
362
+ }
363
+ return localisedSelectedFilters;
364
+ };
365
+
366
+ /** Reduce filters state to a simple object containing all filter keys and the selected values */
367
+ const reduceSelectedFilters = filters => {
255
368
  const selectedFilters = Object.fromEntries(Object.entries(filters).map(([key, filter = {}]) => [key, (filter.items || []).filter(item => !!(item.isSelected || false)).map(item => {
256
369
  const key = (item === null || item === void 0 ? void 0 : item.key) || '';
257
370
  return key;
258
371
  })]));
372
+ return selectedFilters;
373
+ };
374
+
375
+ /** Return keyed object for all filters in the current facet with all selected values for each filter */
376
+ const getSelectedFilters = (state, facet = '', context = Context.facets, returnType) => {
377
+ const filters = getFilters(state, facet, context, 'js');
378
+ const selectedFilters = reduceSelectedFilters(filters);
259
379
  const fromJS = makeFromJS(returnType);
260
380
  return fromJS(selectedFilters);
261
381
  };
382
+
383
+ /** Return keyed object for all _renderable_ filters in the current facet with all selected values for each filter */
384
+ const getRenderableSelectedFilters = (state, facet = '', context = Context.facets) => {
385
+ const filters = getRenderableFilters$2(state, facet, context);
386
+
387
+ // new in CRB4: intended no support for immutable state type
388
+ const selectedFilters = reduceSelectedFilters(filters);
389
+ return selectedFilters;
390
+ };
391
+
392
+ /** A localised version of `getRenderableSelectedFilters` selector */
393
+ const getLocalisedRenderableSelectedFilters = (state, facet = '', context = Context.facets) => {
394
+ const filters = getRenderableSelectedFilters(state, facet, context);
395
+ const localisedFilters = localiseSelectedFilterKeys(filters, state);
396
+ return localisedFilters;
397
+ };
262
398
  const getResults = (state, current = '', context = Context.facets, returnType) => {
263
399
  return getImmutableOrJS(state, ['search', context, current || getCurrent$2(state, context), 'results'], [], returnType);
264
400
  };
401
+ const getResultsInfo = (state, current = '', context = getSearchContext(state)) => {
402
+ return getImmutableOrJS(state, ['search', context, current || getCurrent$2(state, context), 'resultsInfo'], {}, 'js');
403
+ };
265
404
  const getIsInternalPaging = (state, current, context = Context.facets) => {
266
405
  return getImmutableOrJS(state, ['search', context, current || getCurrent$2(state, context), 'queryParams', 'internalPaging'], false);
267
406
  };
@@ -299,6 +438,7 @@ const getTotalCount$1 = (state, current = '', context = Context.facets) => {
299
438
  };
300
439
  const getSearchTerm$2 = state => getImmutableOrJS(state, ['search', 'term']);
301
440
  const getSearchTabs = (state, returnType) => getImmutableOrJS(state, ['search', 'tabs'], [], returnType);
441
+ const getSearchCompositions = state => getImmutableOrJS(state, ['search', 'compositions'], {}, 'js');
302
442
  const getQueryParams = (state, current = '', context = Context.facets) => {
303
443
  return getImmutableOrJS(state, ['search', context, current || getCurrent$2(state, context), 'queryParams'], {}, 'js');
304
444
  };
@@ -312,9 +452,6 @@ const getQueryParameter$2 = ({
312
452
  const getCustomApi = (state, current, context = Context.facets, returnType) => {
313
453
  return getImmutableOrJS(state, ['search', context, current || getCurrent$2(state, context), 'customApi'], null, returnType);
314
454
  };
315
- const getCustomEnv = (state, current, context = Context.facets) => {
316
- return getImmutableOrJS(state, ['search', context, current || getCurrent$2(state, context), 'env']);
317
- };
318
455
  const getTabsAndFacets$1 = (state, returnType) => {
319
456
  const tabs = getSearchTabs(state, 'js');
320
457
  const facets = getFacets(state, 'js');
@@ -355,7 +492,6 @@ const selectFacets = {
355
492
  getCurrent: getCurrentFacet,
356
493
  getCurrentTab: getCurrentTab$1,
357
494
  getCustomApi,
358
- getCustomEnv,
359
495
  getFacet: getFacet$1,
360
496
  getFacetTitles: getFacetTitles$1,
361
497
  getFacets,
@@ -365,6 +501,8 @@ const selectFacets = {
365
501
  getFiltersToLoad,
366
502
  getIsLoaded,
367
503
  getIsLoading: getIsLoading$2,
504
+ /* Localised version of getCurrent */
505
+ getLocalisedCurrent: state => getLocalisedCurrent$2(state, undefined, Context.facets),
368
506
  getPageIndex: getPageIndex$2,
369
507
  getPageIsLoading: getPageIsLoading$2,
370
508
  getPagesLoaded,
@@ -396,6 +534,8 @@ const selectListing = {
396
534
  getFilters: (state, listing = '') => getFilters(state, listing, Context.listings, 'js'),
397
535
  getFiltersToLoad: (state, listing = '') => getFiltersToLoad(state, listing, Context.listings),
398
536
  getListing: getListing$1,
537
+ /* Localised version of getCurrent */
538
+ getLocalisedCurrent: state => getLocalisedCurrent$2(state, undefined, Context.listings),
399
539
  getIsLoaded: state => getIsLoaded(state, Context.listings),
400
540
  getIsLoading: state => getIsLoading$2(state, Context.listings),
401
541
  getPageIndex: (state, listing = '') => getPageIndex$2(state, listing, Context.listings),
@@ -417,23 +557,24 @@ const selectListing = {
417
557
  getTotalCount: (state, listing = '') => getTotalCount$1(state, listing, Context.listings),
418
558
  getSelectedFilters: (state, listing = '') => getSelectedFilters(state, listing, Context.listings, 'js')
419
559
  };
420
- const selectCurrentPath = state => getImmutableOrJS(state, ['routing', 'currentPath']);
421
- const selectCurrentProject = state => getImmutableOrJS(state, ['routing', 'currentProject']);
422
- const selectVersionStatus = state => getImmutableOrJS(state, ['version', 'contensisVersionStatus']);
423
560
 
424
561
  var selectors = /*#__PURE__*/Object.freeze({
425
562
  __proto__: null,
563
+ getComposition: getComposition,
564
+ getCompositionFacets: getCompositionFacets,
426
565
  getCurrent: getCurrent$2,
566
+ getCurrentComposition: getCurrentComposition,
427
567
  getCurrentFacet: getCurrentFacet,
568
+ getCurrentFromLocalised: getCurrentFromLocalised,
428
569
  getCurrentListing: getCurrentListing,
429
570
  getCurrentTab: getCurrentTab$1,
430
571
  getCustomApi: getCustomApi,
431
- getCustomEnv: getCustomEnv,
432
572
  getFacet: getFacet$1,
433
573
  getFacetTitles: getFacetTitles$1,
434
574
  getFacets: getFacets,
435
575
  getFacetsTotalCount: getFacetsTotalCount$1,
436
576
  getFeaturedResults: getFeaturedResults$2,
577
+ getFilterKeyFromLocalised: getFilterKeyFromLocalised,
437
578
  getFilters: getFilters,
438
579
  getFiltersToLoad: getFiltersToLoad,
439
580
  getIsInternalPaging: getIsInternalPaging,
@@ -441,6 +582,10 @@ var selectors = /*#__PURE__*/Object.freeze({
441
582
  getIsLoading: getIsLoading$2,
442
583
  getIsSsr: getIsSsr,
443
584
  getListing: getListing$1,
585
+ getLocalisedCurrent: getLocalisedCurrent$2,
586
+ getLocalisedFacetKey: getLocalisedFacetKey,
587
+ getLocalisedFilterKey: getLocalisedFilterKey,
588
+ getLocalisedRenderableSelectedFilters: getLocalisedRenderableSelectedFilters,
444
589
  getPageIndex: getPageIndex$2,
445
590
  getPageIsLoading: getPageIsLoading$2,
446
591
  getPageSize: getPageSize,
@@ -450,7 +595,10 @@ var selectors = /*#__PURE__*/Object.freeze({
450
595
  getQueryParameter: getQueryParameter$2,
451
596
  getQueryParams: getQueryParams,
452
597
  getRenderableFilters: getRenderableFilters$2,
598
+ getRenderableSelectedFilters: getRenderableSelectedFilters,
453
599
  getResults: getResults,
600
+ getResultsInfo: getResultsInfo,
601
+ getSearchCompositions: getSearchCompositions,
454
602
  getSearchContext: getSearchContext,
455
603
  getSearchTabs: getSearchTabs,
456
604
  getSearchTerm: getSearchTerm$2,
@@ -459,275 +607,29 @@ var selectors = /*#__PURE__*/Object.freeze({
459
607
  getTabFacets: getTabFacets$1,
460
608
  getTabsAndFacets: getTabsAndFacets$1,
461
609
  getTotalCount: getTotalCount$1,
462
- selectCurrentPath: selectCurrentPath,
463
- selectCurrentProject: selectCurrentProject,
464
610
  selectFacets: selectFacets,
465
- selectListing: selectListing,
466
- selectVersionStatus: selectVersionStatus
611
+ selectListing: selectListing
467
612
  });
468
613
 
469
- const now = () => {
470
- if (typeof window == 'undefined') {
471
- return Date.now();
472
- }
473
- return window.performance.now();
474
- };
475
-
476
- const getClientConfig = (project, env) => {
477
- let config = DELIVERY_API_CONFIG; /* global DELIVERY_API_CONFIG */
478
- if (project) {
479
- config.projectId = project;
480
- }
481
- if (typeof window != 'undefined' && PROXY_DELIVERY_API /* global PROXY_DELIVERY_API */) {
482
- // ensure a relative url is used to bypass the need for CORS (separate OPTIONS calls)
483
- config.rootUrl = env || '';
484
- config.responseHandler = {
485
- 404: () => null
486
- };
487
- }
488
- return config;
489
- };
490
- class CacheNode {
491
- constructor(key, value) {
492
- this.key = key;
493
- this.value = value;
494
- this.next = null;
495
- this.prev = null;
496
- }
497
- }
498
- class LruCache {
499
- constructor(limit = 100) {
500
- this.map = {};
501
- this.head = null;
502
- this.tail = null;
503
- this.limit = limit || 100;
504
- this.size = 0;
505
- }
506
- get(key) {
507
- if (this.map[key]) {
508
- let value = this.map[key].value;
509
- let node = new CacheNode(key, value);
510
- this.remove(key);
511
- this.setHead(node);
512
- return value;
513
- }
514
- }
515
- set(key, value) {
516
- let node = new CacheNode(key, value);
517
- if (this.map[key]) {
518
- this.remove(key);
519
- } else {
520
- if (this.size >= this.limit) {
521
- delete this.map[this.tail.key];
522
- this.size--;
523
- this.tail = this.tail.prev;
524
- this.tail.next = null;
525
- }
526
- }
527
- this.setHead(node);
528
- }
529
- setHead(node) {
530
- node.next = this.head;
531
- node.prev = null;
532
- if (this.head) {
533
- this.head.prev = node;
534
- }
535
- this.head = node;
536
- if (!this.tail) {
537
- this.tail = node;
538
- }
539
- this.size++;
540
- this.map[node.key] = node;
541
- }
542
- remove(key) {
543
- let node = this.map[key];
544
- if (node.prev) {
545
- node.prev.next = node.next;
546
- } else {
547
- this.head = node.next;
548
- }
549
- if (node.next) {
550
- node.next.prev = node.prev;
551
- } else {
552
- this.tail = node.prev;
553
- }
554
- delete this.map[key];
555
- this.size--;
556
- }
557
- }
558
- class CachedSearch {
559
- constructor() {
560
- this.cache = new LruCache();
561
- this.taxonomyLookup = {};
562
- }
563
- search(query, linkDepth, project, env) {
564
- const client = Client.create(getClientConfig(project, env));
565
- return this.request(project + JSON.stringify(query) + linkDepth.toString(), () => client.entries.search(query, linkDepth));
566
- }
567
- getTaxonomyNodeByPath(path, project, env) {
568
- const client = Client.create(getClientConfig(project, env));
569
- return this.request(`[TAXONOMY NODE] ${path}`, () => client.taxonomy.getNodeByPath({
570
- path: path,
571
- order: 'defined',
572
- childDepth: 2
573
- }).then(node => this.extendTaxonomyNode(node)));
574
- }
575
- request(key, execute) {
576
- if (!this.cache.get(key) || typeof window == 'undefined') {
577
- let promise = execute();
578
- this.cache.set(key, promise);
579
- promise.catch(() => {
580
- this.cache.remove(key);
581
- });
582
- }
583
- return this.cache.get(key);
584
- }
585
- extendTaxonomyNode(node) {
586
- let id = this.getTaxonomyId(node);
587
- this.taxonomyLookup[id] = node.key;
588
- return {
589
- ...node,
590
- id,
591
- children: node.children ? node.children.map(n => this.extendTaxonomyNode(n)) : null
592
- };
593
- }
594
- getTaxonomyId(node) {
595
- if (node.key) {
596
- let parts = node.key.split('/');
597
- return parts[parts.length - 1];
598
- }
599
- return '';
600
- }
601
- fetch(uri, opts = {}) {
602
- return this.request(`[FETCH] ${uri} ${JSON.stringify(opts)}`, () => fetch(uri, opts));
603
- }
604
- }
605
- const cachedSearch = new CachedSearch();
606
-
607
- function fixFreeTextForElastic(s) {
608
- const illegalChars = ['>', '<', '=', '|', '!', '{', '}', '[', ']', '^', '~', '*', '?', ':', '\\', '/'];
609
- const illegalRegEx = new RegExp(illegalChars.map(c => '\\' + c).join('|'), 'g');
610
- s = s.replace(illegalRegEx, '');
611
- // s = s.replace(encodedRegEx, ''); // (m) => '\\\\' + m);
612
-
613
- return s;
614
- }
615
- /** `convertKeyForAggregation` and `parseKeyForAggregation` exists to prevent an
616
- * auto-generated aggregation using a reserved keyword because Elasticsearch has a list of
617
- * reserved keywords when it parses the response:
618
- * `'location' is one of the reserved aggregation keywords we use a heuristics based
619
- * response parser and using these reserved keywords could throw its heuristics off
620
- * course. We are working on a solution in Elasticsearch itself to make the response
621
- * parseable. For now these are all the reserved keywords: after_key, _as_string,
622
- * bg_count, bottom_right, bounds, buckets, count, doc_count, doc_count_error_upper_bound,
623
- * fields, from, top, type, from_as_string, hits, key, key_as_string, keys, location,
624
- * max_score, meta, min, min_length, score, sum_other_doc_count, to, to_as_string, top_left,
625
- * total, value, value_as_string, values, geometry, properties`
626
- */
627
- const convertKeyForAggregation = key => `sf_${key}`;
628
- const convertFieldIdForAggregation = fieldId => fieldId.replaceAll('[]', '');
629
- const timedSearch = async (query, linkDepth = 0, projectId, env) => {
630
- if (!query) return null;
631
- let duration = 0;
632
- const start = now();
633
- const payload = await cachedSearch.search(query, linkDepth, projectId, env);
634
- const end = now();
635
- duration = Number((end - start).toFixed(2));
636
- return {
637
- duration,
638
- payload
639
- };
640
- };
641
- const getItemsFromResult = result => {
642
- const {
643
- payload
644
- } = result || {};
645
- if (payload) {
646
- if (Array.isArray(payload)) return payload;
647
- if (Array.isArray(payload.items)) return payload.items;
648
- return payload;
649
- }
650
- return [];
651
- };
652
- const extractQuotedPhrases = searchTerm => {
653
- const pattern = new RegExp(/(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')/gm);
654
- return (searchTerm.match(pattern) || []).map(match => match.replace(/"/g, ''));
655
- };
656
- const buildUrl = (route, params) => {
657
- const qs = stringify(params);
658
- const path = qs ? `${route}${route.includes('?') ? '&' : '?'}${qs}` : route;
659
- return path;
660
- };
661
-
662
- /**
663
- * Returns all params from the current route query string or static route
664
- * Supply static route argument if reading parameters from the route path
665
- * Supply location argument for the params to be read in SSR
666
- * @param staticRoute Matched static route from react-router 5 or 6
667
- * @param location location object containing at least pathname and search
668
- * @returns Keyed params object
669
- */
670
- const routeParams = (staticRoute, location) => {
671
- var _staticRoute$match;
672
- // match.params is react-router-config/react-router@5 style
673
- // params is supplied with RouteObject in react-router@6
674
- const pathParams = (staticRoute === null || staticRoute === void 0 || (_staticRoute$match = staticRoute.match) === null || _staticRoute$match === void 0 ? void 0 : _staticRoute$match.params) || (staticRoute === null || staticRoute === void 0 ? void 0 : staticRoute.params) || {};
675
- const queryParams = parse(typeof window !== 'undefined' ? window.location.search : (location === null || location === void 0 ? void 0 : location.search) || '');
676
- return {
677
- ...pathParams,
678
- ...queryParams
679
- };
680
- };
681
- const callCustomApi = async (customApi, filters) => {
682
- const apiUri = customApi.uri || '';
683
- let uri = buildUrl(apiUri, filters);
684
- if (!uri) throw new Error('uri is required to use customApi');
685
- if (typeof window == 'undefined') {
686
- if (!uri.startsWith('http')) uri = `http://localhost:3001${uri}`;
687
- const response = await fetch(uri);
688
- return await response.json();
689
- }
690
- const response = await cachedSearch.fetch(uri);
691
- return await response.clone().json();
692
- };
693
- const removeEmptyAttributes = obj => {
694
- Object.entries(obj).forEach(([key, val]) => val && typeof val === 'object' && removeEmptyAttributes(val) || (typeof val === 'undefined' || val === null || val === '') && delete obj[key]);
695
- return obj;
696
- };
697
- const toArray = (obj, seperator = ',') => typeof obj === 'undefined' || obj === null ? obj : Array.isArray(obj) ? obj : obj.split(seperator);
698
-
699
- // assumes array elements are primitive types
700
- const areArraysEqualSets = (a1, a2) => {
701
- const superSet = {};
702
- for (const ai of a1) {
703
- const e = ai + typeof ai;
704
- superSet[e] = 1;
705
- }
706
- for (const ai of a2) {
707
- const e = ai + typeof ai;
708
- if (!superSet[e]) {
709
- return false;
710
- }
711
- superSet[e] = 2;
712
- }
713
- for (const e in superSet) {
714
- if (superSet[e] === 1) {
715
- return false;
716
- }
717
- }
718
- return true;
719
- };
720
-
721
614
  const searchUriTemplate = {
722
615
  path: ({
723
616
  state,
724
617
  facet
725
618
  }) => {
619
+ var _staticRoute$route;
726
620
  const context = getSearchContext(state);
727
621
  const currentPath = selectCurrentPath(state) || '/search';
728
- if (context !== 'listings') {
729
- const currentFacet = facet || getCurrentFacet(state);
622
+ const staticRoute = selectStaticRoute(state);
623
+ const hasFacetRouteParam = staticRoute === null || staticRoute === void 0 || (_staticRoute$route = staticRoute.route) === null || _staticRoute$route === void 0 || (_staticRoute$route = _staticRoute$route.path) === null || _staticRoute$route === void 0 ? void 0 : _staticRoute$route.includes(`/:${context === 'facets' ? 'facet' : 'listingType'}`);
624
+
625
+ // if (context !== 'listings') {
626
+ if (hasFacetRouteParam) {
627
+ const currentFacet = getLocalisedFacetKey(state, facet) || facet || getLocalisedCurrent$2(state);
730
628
  const filters = getSelectedFilters(state, facet, context);
629
+ // TODO: This only looking for a filter called contentTypeId
630
+ // feels a bit useless and only really serves as an example.
631
+ // We could expand this in future to be configured with the filter or the route
632
+ // e.g. look for a route param matching the filter key in the static route
731
633
  const currentFilter = filters.contentTypeId;
732
634
 
733
635
  // Check if we have a filter first
@@ -745,17 +647,33 @@ const searchUriTemplate = {
745
647
  pageIndex,
746
648
  pageSize
747
649
  }) => {
748
- const searchContext = getSearchContext(state);
650
+ var _staticRoute$route2;
651
+ const context = getSearchContext(state);
652
+ const staticRoute = selectStaticRoute(state);
653
+ // Some listing routes may not have the listingType or facet as a route param
654
+ // include it as a query param to ensure the correct listing/facet is set or updated
655
+ const hasFacetRouteParam = staticRoute === null || staticRoute === void 0 || (_staticRoute$route2 = staticRoute.route) === null || _staticRoute$route2 === void 0 || (_staticRoute$route2 = _staticRoute$route2.path) === null || _staticRoute$route2 === void 0 ? void 0 : _staticRoute$route2.includes(`/:${context === 'facets' ? 'facet' : 'listingType'}`);
656
+ const currentFacet = getLocalisedFacetKey(state, facet) || facet || getLocalisedCurrent$2(state);
657
+ const facetQuery = !hasFacetRouteParam && currentFacet ? {
658
+ [context === 'listings' ? 'listingType' : 'facet']: currentFacet
659
+ } : {};
660
+
749
661
  // Lose stateFilters and currentSearch if a new
750
662
  // term is passed via an argument
751
- const stateFilters = term ? {} : Object.fromEntries(Object.entries(getSelectedFilters(state, facet, searchContext, 'js')).map(([k, f]) => [k, f === null || f === void 0 ? void 0 : f.join(',')]));
663
+ const stateFilters = term ? {} : Object.fromEntries(Object.entries(getLocalisedRenderableSelectedFilters(state, facet, context)).map(([k, f]) => [k, f === null || f === void 0 ? void 0 : f.join(',')]));
752
664
  const currentSearch = !term && getImmutableOrJS(state, ['routing', 'location', 'search']);
753
665
  const currentQs = removeEmptyAttributes(parse(currentSearch));
754
- if (orderBy) currentQs.orderBy = orderBy;
666
+
667
+ // An argument is provided with the updated value
668
+ // when the relevant action has been triggered
669
+ if (typeof orderBy !== 'undefined') currentQs.orderBy = orderBy;
755
670
  const searchTerm = getSearchTerm$2(state);
756
671
  // Use Immutable's merge to merge the stateFilters with any current Qs
757
672
  // to build the new Qs.
758
- const mergedSearch = removeEmptyAttributes(merge(currentQs, stateFilters));
673
+ const mergedSearch = removeEmptyAttributes(merge(currentQs, {
674
+ ...facetQuery,
675
+ ...stateFilters
676
+ }));
759
677
 
760
678
  // We must handle term === '' separately, because this means the user has cleared the search term
761
679
  // If this is true, we don't want to fall back to the existing search term. We only want to do that if the
@@ -791,6 +709,7 @@ const {
791
709
  getFacetTitles,
792
710
  getFeaturedResults: getFeaturedResults$1,
793
711
  getIsLoading: getIsLoading$1,
712
+ getLocalisedCurrent: getLocalisedCurrent$1,
794
713
  getPageIndex: getPageIndex$1,
795
714
  getPageIsLoading: getPageIsLoading$1,
796
715
  getQueryParameter: getQueryParameter$1,
@@ -802,6 +721,8 @@ const {
802
721
  getTotalCount
803
722
  } = selectFacets;
804
723
  const makeSelectFacetsProps = () => createSelector(state => state, (_, mappers) => mappers, (state, mappers) => ({
724
+ composition: getComposition(state),
725
+ currentComposition: getCurrentComposition(state),
805
726
  currentFacet: getCurrent$1(state),
806
727
  currentPageIndex: getPageIndex$1(state),
807
728
  currentTabIndex: getCurrentTab(state),
@@ -812,10 +733,11 @@ const makeSelectFacetsProps = () => createSelector(state => state, (_, mappers)
812
733
  featured: getFeaturedResults$1(state),
813
734
  filters: getRenderableFilters$1(state),
814
735
  isLoading: getIsLoading$1(state),
736
+ localisedCurrent: getLocalisedCurrent$1(state),
815
737
  pageIsLoading: getPageIsLoading$1(state),
816
738
  paging: getPaging(state, '', Context.facets, 'js'),
817
739
  results: getResults(state, '', Context.facets, 'js'),
818
- resultsInfo: mappers && typeof mappers.resultsInfo === 'function' && mappers.resultsInfo(state),
740
+ resultsInfo: typeof (mappers === null || mappers === void 0 ? void 0 : mappers.resultsInfo) === 'function' && mappers.resultsInfo(state) || getResultsInfo(state),
819
741
  searchTerm: getSearchTerm$1(state),
820
742
  searchTotalCount: getSearchTotalCount(state),
821
743
  selectedFilters: getSelectedFilters(state, '', Context.facets, 'js'),
@@ -844,6 +766,8 @@ const useFacets = ({
844
766
  updateSortOrder: orderBy => dispatch(withMappers(updateSortOrder$1(orderBy), m))
845
767
  };
846
768
  const {
769
+ composition,
770
+ currentComposition,
847
771
  currentFacet,
848
772
  currentPageIndex,
849
773
  currentTabIndex,
@@ -854,6 +778,7 @@ const useFacets = ({
854
778
  featured,
855
779
  filters,
856
780
  isLoading,
781
+ localisedCurrent,
857
782
  paging,
858
783
  pageIsLoading,
859
784
  results,
@@ -866,6 +791,8 @@ const useFacets = ({
866
791
  totalCount
867
792
  } = useSelector(state => selectListingProps(state, m));
868
793
  return {
794
+ composition,
795
+ currentComposition,
869
796
  currentFacet,
870
797
  currentPageIndex,
871
798
  currentTabIndex,
@@ -876,6 +803,7 @@ const useFacets = ({
876
803
  featured,
877
804
  filters,
878
805
  isLoading,
806
+ localisedCurrent,
879
807
  paging,
880
808
  pageIsLoading,
881
809
  results,
@@ -895,6 +823,7 @@ const {
895
823
  getFeaturedResults,
896
824
  getIsLoading,
897
825
  getListing,
826
+ getLocalisedCurrent,
898
827
  getPageIndex,
899
828
  getPageIsLoading,
900
829
  getQueryParameter,
@@ -902,16 +831,19 @@ const {
902
831
  getSearchTerm
903
832
  } = selectListing;
904
833
  const makeSelectListingProps = () => createSelector(state => state, (_, mappers) => mappers, (state, mappers) => ({
834
+ composition: getComposition(state),
835
+ currentComposition: getCurrentComposition(state),
905
836
  currentListing: getCurrent(state),
906
837
  currentPageIndex: getPageIndex(state),
907
- listing: getListing(state),
908
838
  featured: getFeaturedResults(state),
909
839
  filters: getRenderableFilters(state),
910
840
  isLoading: getIsLoading(state),
841
+ listing: getListing(state),
842
+ localisedCurrent: getLocalisedCurrent(state),
911
843
  pageIsLoading: getPageIsLoading(state),
912
844
  paging: getPaging(state, '', Context.listings, 'js'),
913
845
  results: getResults(state, '', Context.listings, 'js'),
914
- resultsInfo: mappers && typeof mappers.resultsInfo === 'function' && mappers.resultsInfo(state),
846
+ resultsInfo: typeof mappers.resultsInfo === 'function' && mappers.resultsInfo(state) || getResultsInfo(state),
915
847
  searchTerm: getSearchTerm(state),
916
848
  selectedFilters: getSelectedFilters(state, '', Context.listings, 'js'),
917
849
  sortOrder: getQueryParameter({
@@ -936,12 +868,15 @@ const useListing = ({
936
868
  updateSortOrder: orderBy => dispatch(withMappers(updateSortOrder$1(orderBy), m))
937
869
  };
938
870
  const {
871
+ composition,
872
+ currentComposition,
939
873
  currentListing,
940
874
  currentPageIndex,
941
875
  featured,
942
876
  filters,
943
877
  isLoading,
944
878
  listing,
879
+ localisedCurrent,
945
880
  paging,
946
881
  pageIsLoading,
947
882
  results,
@@ -951,12 +886,15 @@ const useListing = ({
951
886
  sortOrder
952
887
  } = useSelector(state => selectListingProps(state, m));
953
888
  return {
889
+ composition,
890
+ currentComposition,
954
891
  currentListing,
955
892
  currentPageIndex,
956
893
  featured,
957
894
  filters,
958
895
  isLoading,
959
896
  listing,
897
+ localisedCurrent,
960
898
  pageIsLoading,
961
899
  paging,
962
900
  results,
@@ -969,11 +907,53 @@ const useListing = ({
969
907
  };
970
908
  };
971
909
 
910
+ class CachedTaxonomyLookup {
911
+ constructor() {
912
+ this.cache = new LruCache();
913
+ this.taxonomyLookup = {};
914
+ }
915
+ getTaxonomyNodeByPath(path, project, env) {
916
+ const client = Client.create(getClientConfig(project, env));
917
+ return this.request(`[TAXONOMY] ${path}`, () => client.taxonomy.getNodeByPath({
918
+ path: path,
919
+ order: 'defined',
920
+ childDepth: 2
921
+ }).then(node => this.extendTaxonomyNode(node)));
922
+ }
923
+ request(key, execute) {
924
+ if (!this.cache.get(key) || typeof window == 'undefined') {
925
+ let promise = execute();
926
+ this.cache.set(key, promise);
927
+ promise.catch(() => {
928
+ this.cache.remove(key);
929
+ });
930
+ }
931
+ return this.cache.get(key);
932
+ }
933
+ extendTaxonomyNode(node) {
934
+ let id = this.getTaxonomyId(node);
935
+ this.taxonomyLookup[id] = node.key;
936
+ return {
937
+ ...node,
938
+ id,
939
+ children: node.children ? node.children.map(n => this.extendTaxonomyNode(n)) : null
940
+ };
941
+ }
942
+ getTaxonomyId(node) {
943
+ if (node.key) {
944
+ let parts = node.key.split('/');
945
+ return parts[parts.length - 1];
946
+ }
947
+ return '';
948
+ }
949
+ }
950
+
951
+ /** @deprecated Taxonomy is deprecated in Contensis, code remains
952
+ * to support any legacy implementations using Taxonomy in their search */
953
+ const cachedTaxonomyLookup = new CachedTaxonomyLookup();
954
+
972
955
  const DataFormats = {
973
- asset: 'asset',
974
- entry: 'entry',
975
- webpage: 'webpage'
976
- };
956
+ entry: 'entry'};
977
957
  const FilterExpressionTypes = {
978
958
  contentType: 'contentType',
979
959
  field: 'field'
@@ -1008,16 +988,20 @@ const fieldExpression = (field, value, operator = 'equalTo', weight, fuzzySearch
1008
988
  const contentTypeIdExpression = (contentTypeIds, webpageTemplates, assetTypes) => {
1009
989
  const expressions = [];
1010
990
  if (!contentTypeIds && !webpageTemplates && !assetTypes) return expressions;
1011
- if (contentTypeIds && contentTypeIds.length > 0) {
1012
- expressions.push(...dataFormatExpression(contentTypeIds, DataFormats.entry));
1013
- }
1014
- if (webpageTemplates && webpageTemplates.length > 0) {
1015
- expressions.push(...dataFormatExpression(webpageTemplates, DataFormats.webpage));
991
+ const ids = [...new Set([...(contentTypeIds || []), ...(webpageTemplates || []), ...(assetTypes || [])])];
992
+
993
+ /**
994
+ * We have an array of contentTypeIds some may be prefixed with a "!"
995
+ * to indicate this is a "not" expression
996
+ */
997
+ const withContentTypeIds = ids.filter(c => !c.startsWith('!'));
998
+ const notContentTypeIds = ids.filter(c => c.startsWith('!')).map(id => id.substring(1));
999
+ if (withContentTypeIds.length > 0) {
1000
+ expressions.push(...fieldExpression(Fields.sys.contentTypeId, withContentTypeIds));
1016
1001
  }
1017
- if (assetTypes && assetTypes.length > 0) {
1018
- expressions.push(...dataFormatExpression(assetTypes, DataFormats.asset));
1002
+ if (notContentTypeIds.length > 0) {
1003
+ expressions.push(Op.not(fieldExpression(Fields.sys.contentTypeId, notContentTypeIds)[0]));
1019
1004
  }
1020
- if (expressions.length > 1) return [Op.or(...expressions)];
1021
1005
  return expressions;
1022
1006
  };
1023
1007
  const filterExpressions = (filters, isOptional = false) => {
@@ -1040,6 +1024,9 @@ const filterExpressions = (filters, isOptional = false) => {
1040
1024
  });
1041
1025
  return expressions;
1042
1026
  };
1027
+
1028
+ /** @deprecated since v4 - contentTypeIdExpression produces a simpler more efficient query
1029
+ * now and negates the need for supplying `sys.dataFormat` with `sys.contentTypeId` */
1043
1030
  const dataFormatExpression = (contentTypeIds, dataFormat = DataFormats.entry) => {
1044
1031
  if (contentTypeIds && contentTypeIds.length > 0) {
1045
1032
  /**
@@ -1150,7 +1137,6 @@ const between = (field, value) => {
1150
1137
  const [minimum, maximum] = valArr;
1151
1138
  return Op.between(field, minimum, maximum);
1152
1139
  } else {
1153
- // eslint-disable-next-line no-console
1154
1140
  console.log(`[search] You have supplied only one value to a "between" operator which must have two values. Your supplied value "${valArr.length && valArr[0]}" has been discarded.`);
1155
1141
  return false;
1156
1142
  }
@@ -1167,7 +1153,6 @@ const distanceWithin = (field, value) => {
1167
1153
  const [lat, lon] = valArr;
1168
1154
  return Op.distanceWithin(field, Number(lat), Number(lon), (valArr === null || valArr === void 0 ? void 0 : valArr[2]) || '10mi');
1169
1155
  } else {
1170
- // eslint-disable-next-line no-console
1171
1156
  console.log(`[search] You have supplied only one value to a "distanceWithin" operator which must be made up of "lat,lon,distance". Your supplied value "${valArr.length && valArr[0]}" has been discarded.`);
1172
1157
  return false;
1173
1158
  }
@@ -1320,10 +1305,10 @@ var expressions = /*#__PURE__*/Object.freeze({
1320
1305
  termExpressions: termExpressions
1321
1306
  });
1322
1307
 
1323
- const filterQuery = (contentTypeIds, versionStatus, customWhere) => {
1324
- const query = new Query(...[...contentTypeIdExpression(contentTypeIds), ...defaultExpressions(versionStatus), ...customWhereExpressions(customWhere)]);
1308
+ const filterQuery = (contentTypeIds, languages, versionStatus, customWhere, pageSize = 100) => {
1309
+ const query = new Query(...[...contentTypeIdExpression(contentTypeIds), ...languagesExpression(languages), ...defaultExpressions(versionStatus), ...customWhereExpressions(customWhere)]);
1325
1310
  query.orderBy = OrderBy.asc(Fields.entryTitle);
1326
- query.pageSize = 100;
1311
+ query.pageSize = pageSize;
1327
1312
  return query;
1328
1313
  };
1329
1314
  const searchQuery = ({
@@ -5055,13 +5040,59 @@ const facetTemplate = {
5055
5040
  state,
5056
5041
  action
5057
5042
  }) => {
5058
- const aggregations = 'aggregations' in result.payload ? result.payload.aggregations : undefined;
5043
+ const aggregations = result.payload && 'aggregations' in result.payload ? result.payload.aggregations : undefined;
5059
5044
  if (!aggregations) return {};
5060
5045
 
5061
- // Handle aggregations client-side where the filter items have loaded before the results containing the aggregations
5046
+ // Handle aggregations client-side where the filter items have loaded
5047
+ // before the results containing the aggregations
5062
5048
  const filters = cloneDeep(getFilters(state, action.facet, action.context, 'js'));
5063
- for (const [filterKey, filter] of Object.entries(filters)) {
5064
- const aggregation = aggregations[convertKeyForAggregation(filterKey)];
5049
+ for (const filter of Object.values(filters)) {
5050
+ let aggregation = {};
5051
+ if (typeof filter.fieldId === 'string') {
5052
+ aggregation = aggregations[convertKeyForAggregation(filter.fieldId)] || {};
5053
+ } else if (Array.isArray(filter.fieldId)) {
5054
+ for (const fieldId of filter.fieldId) {
5055
+ aggregation = merge(aggregation, aggregations[convertKeyForAggregation(fieldId)] || {});
5056
+ }
5057
+ }
5058
+ // Populate filter items from aggregations for example tag fields
5059
+ if (filter.aggregations) {
5060
+ // Use supplied aggregations instead of field aggregations
5061
+ if (typeof filter.aggregations === 'string') {
5062
+ aggregation = aggregations[convertKeyForAggregation(filter.aggregations)] || {};
5063
+ } else if (Array.isArray(filter.aggregations)) {
5064
+ aggregation = {};
5065
+ for (const fieldId of filter.aggregations) {
5066
+ aggregation = merge(aggregation, aggregations[convertKeyForAggregation(fieldId)] || {});
5067
+ }
5068
+ }
5069
+ // Start with existing items that are not in the aggregation
5070
+ const existingItemsNotInAggregation = (filter.items || []).filter(item => !(item.key in (aggregation || {}))).map(item => {
5071
+ delete item.aggregate;
5072
+ return item;
5073
+ });
5074
+
5075
+ // Map aggregation entries to filter items
5076
+ const aggregationItems = Object.entries(aggregation || {}).map(([key, aggregate]) => {
5077
+ var _filter$items;
5078
+ const existing = ((_filter$items = filter.items) === null || _filter$items === void 0 ? void 0 : _filter$items.find(item => item.key === key)) || {};
5079
+ return {
5080
+ key,
5081
+ title: (existing === null || existing === void 0 ? void 0 : existing.title) || `${key[0].toUpperCase()}${key.slice(1)}`,
5082
+ isSelected: !!(existing !== null && existing !== void 0 && existing.isSelected),
5083
+ aggregate
5084
+ };
5085
+ });
5086
+
5087
+ // Combine existing items not in aggregation with aggregation items
5088
+ filter.items = [...existingItemsNotInAggregation, ...aggregationItems].sort((a, b) => (a.title || a.key).localeCompare(b.title || b.key));
5089
+ continue;
5090
+ }
5091
+
5092
+ // Update aggregation counts on existing filter items
5093
+ // In the context of a pre-loaded facet, the filter items will
5094
+ // not have been loaded yet, so we need to check again when
5095
+ // the filter items load and populate the aggregate counts then as well
5065
5096
  for (const filterItem of filter.items || []) {
5066
5097
  if (!aggregation) delete filterItem.aggregate;else {
5067
5098
  const aggregate = aggregation[filterItem.key.toLowerCase()];
@@ -5142,6 +5173,7 @@ const facetTemplate = {
5142
5173
  },
5143
5174
  preload: 'action.preload',
5144
5175
  ogState: 'action.ogState',
5176
+ state: 'state',
5145
5177
  debug: 'action.debug'
5146
5178
  };
5147
5179
  const filterTemplate = {
@@ -5161,7 +5193,7 @@ const filterTemplate = {
5161
5193
  selectedKeys,
5162
5194
  mapper,
5163
5195
  facet,
5164
- filterKey
5196
+ filter
5165
5197
  }) => {
5166
5198
  // Handle taxonomy filter items
5167
5199
  if (payload && 'children' in payload) {
@@ -5174,10 +5206,18 @@ const filterTemplate = {
5174
5206
  }
5175
5207
 
5176
5208
  // Handle entries-based filter items
5177
- if (payload && 'items' in payload) {
5178
- var _facet$aggregations;
5209
+ if (payload && 'items' in payload && filter.fieldId) {
5210
+ var _facet$aggregations2;
5179
5211
  // Handle aggregations from SSR where the results containing the aggregations have loaded before the filter items
5180
- const aggregation = (_facet$aggregations = facet.aggregations) === null || _facet$aggregations === void 0 ? void 0 : _facet$aggregations[convertKeyForAggregation(filterKey)];
5212
+ const aggregation = Array.isArray(filter.fieldId) ? filter.fieldId.reduce((agg, fieldId) => {
5213
+ var _facet$aggregations;
5214
+ const fieldAggregations = ((_facet$aggregations = facet.aggregations) === null || _facet$aggregations === void 0 ? void 0 : _facet$aggregations[convertKeyForAggregation(fieldId)]) || {};
5215
+ // Accumulate numeric values for matching keys from previous counted fields
5216
+ for (const [key, value] of Object.entries(fieldAggregations)) {
5217
+ agg[key] = (agg[key] || 0) + value;
5218
+ }
5219
+ return agg;
5220
+ }, {}) : (_facet$aggregations2 = facet.aggregations) === null || _facet$aggregations2 === void 0 ? void 0 : _facet$aggregations2[convertKeyForAggregation(filter.fieldId)];
5181
5221
  const items = payload.items.map(item => {
5182
5222
  var _item$sys, _item$sys2;
5183
5223
  item.isSelected = selectedKeys === null || selectedKeys === void 0 ? void 0 : selectedKeys.includes(item === null || item === void 0 || (_item$sys = item.sys) === null || _item$sys === void 0 ? void 0 : _item$sys.id);
@@ -5185,7 +5225,7 @@ const filterTemplate = {
5185
5225
  if (typeof aggregate === 'number') item.aggregate = aggregate;
5186
5226
  return item;
5187
5227
  });
5188
- return mapper === null || mapper === void 0 ? void 0 : mapper(items);
5228
+ return (mapper === null || mapper === void 0 ? void 0 : mapper(items)) || [];
5189
5229
  }
5190
5230
  return [];
5191
5231
  }
@@ -5242,10 +5282,22 @@ const queryParamsTemplate = {
5242
5282
  } = root;
5243
5283
  const stateFilters = getFilters(state, facet, context, 'js');
5244
5284
  const aggregations = {};
5245
- for (const [filterKey, filter] of Object.entries(stateFilters)) {
5246
- if (filter.fieldId && !Array.isArray(filter.fieldId)) {
5247
- aggregations[convertKeyForAggregation(filterKey)] = {
5248
- field: convertFieldIdForAggregation(filter.fieldId),
5285
+ for (const filter of Object.values(stateFilters)) {
5286
+ if (Array.isArray(filter.fieldId)) {
5287
+ for (const id of filter.fieldId) {
5288
+ const field = cleanseFieldIdForAggregation(id);
5289
+ const aggregationKey = convertKeyForAggregation(field);
5290
+ if (!aggregations[aggregationKey]) {
5291
+ aggregations[aggregationKey] = {
5292
+ field,
5293
+ size: 100
5294
+ };
5295
+ }
5296
+ }
5297
+ } else if (filter.fieldId) {
5298
+ const field = cleanseFieldIdForAggregation(filter.fieldId);
5299
+ aggregations[convertKeyForAggregation(field)] = {
5300
+ field,
5249
5301
  size: 100
5250
5302
  };
5251
5303
  }
@@ -5259,11 +5311,6 @@ const queryParamsTemplate = {
5259
5311
  contentTypeIds: root => getQueryParameter$2(root, 'contentTypeIds', []),
5260
5312
  customWhere: root => getQueryParameter$2(root, 'customWhere', []),
5261
5313
  dynamicOrderBy: root => getQueryParameter$2(root, 'dynamicOrderBy', []),
5262
- env: ({
5263
- state,
5264
- facet,
5265
- context
5266
- }) => getCustomEnv(state, facet, context),
5267
5314
  excludeIds: ({
5268
5315
  action: {
5269
5316
  excludeIds
@@ -5294,9 +5341,7 @@ const queryParamsTemplate = {
5294
5341
  state
5295
5342
  }) => getPageIndex$2(state, '', action.context),
5296
5343
  internalPaging: root => getQueryParameter$2(root, 'internalPaging', false),
5297
- languages: ({
5298
- action
5299
- }) => action.defaultLang ? [action.defaultLang] : [],
5344
+ languages: root => getQueryParameter$2(root, 'languages', []),
5300
5345
  linkDepth: root => getQueryParameter$2(root, 'linkDepth', 0),
5301
5346
  loadMorePaging: root => getQueryParameter$2(root, 'loadMorePaging', false),
5302
5347
  omitDefaultSearchFields: root => getQueryParameter$2(root, 'omitDefaultSearchFields', []),
@@ -5386,23 +5431,30 @@ const generateQueryParams = (action, state) => {
5386
5431
  const runSearch = (action, state, queryParams) => {
5387
5432
  const {
5388
5433
  context,
5389
- defaultLang,
5434
+ // defaultLang,
5390
5435
  facet,
5391
5436
  ogState = state,
5392
5437
  preload,
5393
- ssr
5438
+ isSSR
5394
5439
  } = action;
5395
5440
  let willRun = false;
5396
- const facetIsLoaded = defaultLang ? false : getIsLoaded(state, context, facet);
5441
+
5442
+ // const facetIsLoaded = defaultLang
5443
+ // ? false
5444
+ // : getIsLoaded(state, context, facet);
5445
+ const facetIsLoaded = getIsLoaded(state, context, facet);
5397
5446
  const stateParams = {
5398
5447
  ...getQueryParams(ogState, facet, context)
5399
5448
  };
5400
5449
  stateParams.pageIndex = getPageIndex$2(ogState, facet, context);
5401
5450
  stateParams.searchTerm = getSearchTerm$2(ogState);
5402
5451
  stateParams.pageSize = getPageSize(ogState, facet, context);
5403
- if (context === Context.facets && ssr ||
5452
+ if (isSSR ||
5453
+ // (context === Context.facets && isSSR) ||
5404
5454
  // context === Context.minilist ||
5405
- preload || !facetIsLoaded || filterParamsChanged(action) || defaultLang) {
5455
+ preload || !facetIsLoaded || filterParamsChanged(action) ||
5456
+ // || defaultLang
5457
+ languageChanged(action)) {
5406
5458
  willRun = true;
5407
5459
  } else {
5408
5460
  // Don't execute the search if the inbound query params
@@ -5421,6 +5473,20 @@ const runSearch = (action, state, queryParams) => {
5421
5473
  return willRun;
5422
5474
  };
5423
5475
 
5476
+ /**
5477
+ * Patch mutates original params argument to decode certain
5478
+ * url encoded params which can creep into urls and cause a
5479
+ * flash of different content when hydrating from SSR
5480
+ * @param params SearchParams
5481
+ * @returns SearchParams
5482
+ */
5483
+ const sanitiseParams = params => {
5484
+ if (params && typeof params === 'object') for (const param of Object.keys(params)) {
5485
+ if (typeof params[param] === 'string') params[param] = params[param].replaceAll('%2C', ',');
5486
+ }
5487
+ return params;
5488
+ };
5489
+
5424
5490
  /**
5425
5491
  * This will tell us if filter parameters have been
5426
5492
  * changed by some external event such as a route change
@@ -5441,8 +5507,13 @@ const filterParamsChanged = (action, state) => {
5441
5507
  });
5442
5508
  return paramsChanged.filter(f => f === true).length > 0;
5443
5509
  };
5444
-
5445
- /* eslint-disable no-console */
5510
+ const languageChanged = action => {
5511
+ const stateLanguages = getQueryParameter$2({
5512
+ ...action,
5513
+ state: action.ogState
5514
+ }, 'languages', []);
5515
+ return !areArraysEqualSets(action.languages || [], stateLanguages);
5516
+ };
5446
5517
  const debugExecuteSearch = (action, state) => {
5447
5518
  const [queryParams, runSearch] = generateQueryParams(action, state);
5448
5519
  console.log('runSearch', runSearch, 'action', action, 'filterParamsChanged', filterParamsChanged(action, state), 'getIsLoaded(state, context, facet)', getIsLoaded(state, action.context, action.facet));
@@ -5523,35 +5594,97 @@ function* setRouteFilters(action) {
5523
5594
  const {
5524
5595
  mappers,
5525
5596
  params,
5526
- listingType,
5527
- defaultLang,
5528
- debug
5597
+ composition,
5598
+ debug,
5599
+ ssr
5600
+ } = action;
5601
+ let {
5602
+ defaultLang
5529
5603
  } = action;
5530
- const context = listingType ? Context.listings : Context.facets;
5531
5604
  const state = toJS(yield select());
5532
- const ssr = getIsSsr(state);
5605
+ const isSSR = getIsSsr(state);
5606
+ sanitiseParams(params);
5533
5607
 
5534
5608
  // Get current facet from params or state
5535
- let currentFacet = params && params.facet || listingType;
5609
+ const facet = (params === null || params === void 0 ? void 0 : params.facet) || action.facet;
5610
+ const listingType = (params === null || params === void 0 ? void 0 : params.listingType) || action.listingType;
5611
+
5612
+ // Determine facets or listings context
5613
+ let context = listingType ? Context.listings : Context.facets;
5614
+ let currentFacet = listingType || facet;
5615
+
5616
+ // Instead of just taking the facet/listing from params,
5617
+ // we need to check all aliases to determine the correct facet/listing
5618
+ const currentLanguage = yield select(selectCurrentLanguage);
5619
+ if (currentFacet) {
5620
+ const currentLocalised = yield select(getCurrentFromLocalised, currentFacet, currentLanguage, context);
5621
+ if (currentLocalised) {
5622
+ currentFacet = currentLocalised.facet;
5623
+ defaultLang = currentLocalised.language;
5624
+ }
5625
+ }
5626
+
5627
+ // If composition is set, and no facet/listingType in params,
5628
+ // pick the first facet/listing from the composition
5629
+ if (composition) {
5630
+ const compositions = getSearchCompositions(state);
5631
+ const compositionConfig = compositions[composition];
5632
+ if (compositionConfig) {
5633
+ if ('facets' in compositionConfig) {
5634
+ if (!facet) {
5635
+ var _compositionConfig$fa;
5636
+ const firstFacetKey = (_compositionConfig$fa = compositionConfig.facets) === null || _compositionConfig$fa === void 0 ? void 0 : _compositionConfig$fa[0];
5637
+ context = Context.facets;
5638
+ currentFacet = firstFacetKey;
5639
+ }
5640
+ } else if ('listings' in compositionConfig) {
5641
+ if (!listingType) {
5642
+ var _compositionConfig$li;
5643
+ const firstListingKey = (_compositionConfig$li = compositionConfig.listings) === null || _compositionConfig$li === void 0 ? void 0 : _compositionConfig$li[0];
5644
+ context = Context.listings;
5645
+ currentFacet = firstListingKey;
5646
+ }
5647
+ }
5648
+ }
5649
+ }
5536
5650
 
5537
5651
  // If Listing use listing type (ignore params.facet)
5538
- if (context === Context.listings) {
5652
+ if (context === Context.listings && listingType) {
5539
5653
  currentFacet = listingType;
5540
5654
  }
5541
5655
 
5542
5656
  // Pick the default facet from initialState
5543
5657
  if (!currentFacet) {
5544
- var _Object$keys;
5658
+ var _tabs$, _Object$keys;
5545
5659
  const tabs = getSearchTabs(state, 'js');
5546
- currentFacet = (tabs === null || tabs === void 0 ? void 0 : tabs[0].defaultFacet) || ((_Object$keys = Object.keys(getFacets(state, 'js'))) === null || _Object$keys === void 0 ? void 0 : _Object$keys[0]) || '';
5660
+ currentFacet = (tabs === null || tabs === void 0 || (_tabs$ = tabs[0]) === null || _tabs$ === void 0 ? void 0 : _tabs$.defaultFacet) || ((_Object$keys = Object.keys(getFacets(state, 'js'))) === null || _Object$keys === void 0 ? void 0 : _Object$keys[0]) || '';
5661
+ }
5662
+
5663
+ // Ensure we have a language set
5664
+ if (!defaultLang) defaultLang = currentLanguage;
5665
+
5666
+ // When we have a currentFacet, check the defaultLang
5667
+ // and translate any filter params from the localised aliases
5668
+ // to the actual filter keys
5669
+ if (currentFacet && defaultLang) {
5670
+ for (const paramKey of Object.keys(params || {})) {
5671
+ const filterKey = yield select(getFilterKeyFromLocalised, paramKey, defaultLang, currentFacet, context);
5672
+ if (filterKey && filterKey !== paramKey) {
5673
+ params[filterKey] = params[paramKey];
5674
+ delete params[paramKey];
5675
+ }
5676
+ }
5547
5677
  }
5548
5678
  const nextAction = {
5549
5679
  type: SET_ROUTE_FILTERS,
5550
5680
  context,
5681
+ composition,
5551
5682
  facet: currentFacet,
5552
5683
  mappers,
5553
5684
  params,
5554
5685
  defaultLang,
5686
+ languages: defaultLang ? [defaultLang] : [],
5687
+ isSSR,
5555
5688
  ssr,
5556
5689
  debug
5557
5690
  };
@@ -5583,7 +5716,7 @@ function* doSearch(action) {
5583
5716
  const nextAction = {
5584
5717
  ...action,
5585
5718
  type: SET_SEARCH_FILTERS,
5586
- ssr: getIsSsr(state),
5719
+ isSSR: getIsSsr(state),
5587
5720
  facet: action.facet || ((_action$params = action.params) === null || _action$params === void 0 ? void 0 : _action$params.facet)
5588
5721
  };
5589
5722
  if (nextAction.facet && (action.config || Object.keys(getFacet$1(state, nextAction.facet, action.context, 'js')).length > 0)) {
@@ -5603,7 +5736,9 @@ function* loadFilters(action) {
5603
5736
  const {
5604
5737
  facet: facetKey,
5605
5738
  context,
5606
- mappers = {}
5739
+ mappers = {},
5740
+ languages,
5741
+ ssr
5607
5742
  } = action;
5608
5743
  const filtersToLoad = yield select(getFiltersToLoad, facetKey, context, 'js');
5609
5744
  if (filtersToLoad.length > 0) {
@@ -5611,7 +5746,8 @@ function* loadFilters(action) {
5611
5746
  type: LOAD_FILTERS,
5612
5747
  filtersToLoad,
5613
5748
  facetKey,
5614
- context
5749
+ context,
5750
+ languages
5615
5751
  });
5616
5752
  const selectedKeys = yield select(getSelectedFilters, facetKey, context, 'js');
5617
5753
  const facet = yield select(getFacet$1, facetKey, context, 'js');
@@ -5623,9 +5759,11 @@ function* loadFilters(action) {
5623
5759
  filterKey,
5624
5760
  filter: filters[filterKey],
5625
5761
  projectId,
5762
+ languages,
5626
5763
  selectedKeys: selectedKeys[filterKey],
5627
5764
  context,
5628
- mapper: 'filterItems' in mappers && mappers.filterItems || mapEntriesToFilterItems
5765
+ mapper: 'filterItems' in mappers && mappers.filterItems || mapEntriesToFilterItems,
5766
+ ssr
5629
5767
  });
5630
5768
  });
5631
5769
  if (filtersToLoadSagas) yield all(filtersToLoadSagas);
@@ -5633,17 +5771,26 @@ function* loadFilters(action) {
5633
5771
  }
5634
5772
  function* loadFilter(action) {
5635
5773
  const {
5774
+ context,
5636
5775
  facetKey,
5637
- filterKey,
5638
5776
  filter,
5777
+ filterKey,
5778
+ languages,
5779
+ mapper,
5639
5780
  projectId,
5640
5781
  selectedKeys,
5641
- context,
5642
- mapper
5782
+ // get api instance from SSR context that is connected to the current request in SSR,
5783
+ // fall back to the imported cachedSearch api that is not connected to the current SSR context
5784
+ ssr: {
5785
+ api
5786
+ } = {
5787
+ api: cachedSearch
5788
+ }
5643
5789
  } = action;
5644
5790
  const {
5645
5791
  contentTypeId,
5646
5792
  customWhere,
5793
+ pageSize,
5647
5794
  path
5648
5795
  } = filter;
5649
5796
  const createStateFrom = {
@@ -5651,6 +5798,7 @@ function* loadFilter(action) {
5651
5798
  context,
5652
5799
  error: undefined,
5653
5800
  facetKey,
5801
+ filter,
5654
5802
  filterKey,
5655
5803
  payload: {},
5656
5804
  selectedKeys,
@@ -5659,15 +5807,15 @@ function* loadFilter(action) {
5659
5807
  try {
5660
5808
  if (contentTypeId) {
5661
5809
  const versionStatus = yield select(selectVersionStatus);
5662
- const query = filterQuery(Array.isArray(contentTypeId) ? contentTypeId : [contentTypeId], versionStatus, customWhere);
5663
- const payload = yield cachedSearch.search(query, 0, projectId);
5810
+ const query = filterQuery(Array.isArray(contentTypeId) ? contentTypeId : [contentTypeId], languages, versionStatus, customWhere, pageSize);
5811
+ const payload = yield api.search(query, 0, projectId);
5664
5812
  if (!payload) throw new Error('No payload returned by search');
5665
5813
  if (payload.type === 'error') throw payload;
5666
5814
  createStateFrom.payload = payload;
5667
5815
  }
5668
5816
  if (path) {
5669
- const payload = yield cachedSearch.getTaxonomyNodeByPath(path, projectId);
5670
- if (!payload) throw new Error(`No payload returned for taxonomy path: '${path}'`);
5817
+ const payload = yield cachedTaxonomyLookup.getTaxonomyNodeByPath(path, projectId);
5818
+ if (!payload) throw new Error(`Nothing returned for taxonomy: '${path}'`);
5671
5819
  if (payload.type === 'error') throw payload;
5672
5820
  createStateFrom.payload = payload;
5673
5821
  }
@@ -5710,7 +5858,7 @@ function* ensureSearch(action) {
5710
5858
  });
5711
5859
  }
5712
5860
  } catch (error) {
5713
- log.error(...['Error running search saga:', error, error.stack]);
5861
+ log.error('Error running ensureSearch:', error, error.stack);
5714
5862
  }
5715
5863
  }
5716
5864
  function* executeSearch(action) {
@@ -5718,7 +5866,8 @@ function* executeSearch(action) {
5718
5866
  context,
5719
5867
  facet,
5720
5868
  queryParams,
5721
- mappers
5869
+ mappers,
5870
+ ssr
5722
5871
  } = action;
5723
5872
  try {
5724
5873
  const state = yield select();
@@ -5728,19 +5877,19 @@ function* executeSearch(action) {
5728
5877
  const customApi = getCustomApi(state, facet, context, 'js');
5729
5878
  if (customApi) {
5730
5879
  const apiParams = typeof mappers === 'object' && typeof mappers.customApi === 'function' && mappers.customApi(queryParams) || mapQueryParamsToCustomApi(queryParams);
5731
- result.payload = yield callCustomApi(customApi, apiParams);
5880
+ result.payload = yield callCustomApi(customApi, apiParams, ssr);
5732
5881
  result.duration = 1;
5733
5882
  } else {
5734
5883
  if (queryParams.featuredResults) {
5735
5884
  featuredQuery = searchQuery(queryParams, true);
5736
- featuredResult = yield timedSearch(featuredQuery, queryParams.linkDepth, queryParams.projectId, queryParams.env);
5885
+ featuredResult = yield timedSearch(featuredQuery, queryParams.linkDepth, queryParams.projectId, ssr);
5737
5886
  queryParams.excludeIds = getItemsFromResult(featuredResult).map(fi => {
5738
5887
  var _fi$sys;
5739
5888
  return fi === null || fi === void 0 || (_fi$sys = fi.sys) === null || _fi$sys === void 0 ? void 0 : _fi$sys.id;
5740
5889
  }).filter(fi => typeof fi === 'string');
5741
5890
  }
5742
5891
  const query = searchQuery(queryParams);
5743
- result = yield timedSearch(query, queryParams.linkDepth, queryParams.projectId, queryParams.env);
5892
+ result = yield timedSearch(query, queryParams.linkDepth, queryParams.projectId, ssr);
5744
5893
  }
5745
5894
  const createStateFrom = {
5746
5895
  action,
@@ -5753,7 +5902,7 @@ function* executeSearch(action) {
5753
5902
  const nextAction = mapJson(createStateFrom, facetTemplate);
5754
5903
  yield put(nextAction);
5755
5904
  } catch (error) {
5756
- log.error(...['Error running search saga:', error, error.stack]);
5905
+ log.error('Error running executeSearch:', error, error.stack);
5757
5906
  }
5758
5907
  }
5759
5908
  function* preloadOtherFacets(action) {
@@ -5764,9 +5913,10 @@ function* preloadOtherFacets(action) {
5764
5913
  debug
5765
5914
  } = action;
5766
5915
  const state = yield select();
5767
- const currentFacet = getCurrentFacet(state);
5768
- if (!preload && facet === currentFacet && context !== Context.listings) {
5769
- const allFacets = getFacets(state, 'js');
5916
+ const currentFacet = getCurrent$2(state, context);
5917
+ const currentComposition = getCurrentComposition(state);
5918
+ if (!preload && facet === currentFacet && (context !== Context.listings || currentComposition)) {
5919
+ const allFacets = currentComposition ? getCompositionFacets(state, currentComposition) : getFacets(state, 'js');
5770
5920
  const otherFacets = Object.keys(allFacets).filter(f => f !== currentFacet);
5771
5921
  yield all(otherFacets.map((preloadFacet = '') => {
5772
5922
  const preloadAction = {
@@ -5807,9 +5957,13 @@ function* updateCurrentTab(action) {
5807
5957
  }
5808
5958
  function* clearFilters(action) {
5809
5959
  const {
5960
+ clear,
5810
5961
  mappers
5811
5962
  } = action;
5812
- const uri = yield buildUri({}, mappers);
5963
+ const term = clear !== null && clear !== void 0 && clear.term ? '' : undefined;
5964
+ const uri = yield buildUri({
5965
+ term
5966
+ }, mappers);
5813
5967
  yield put(navigate(uri));
5814
5968
  }
5815
5969
  function* updateCurrentFacet(action) {
@@ -5912,5 +6066,5 @@ function* triggerSearchSsr(options) {
5912
6066
  yield call(setRouteFilters, options);
5913
6067
  }
5914
6068
 
5915
- export { useFacets as $, updateCurrentFacet$1 as A, clearFilters$1 as B, selectListing as C, triggerSearch as D, Context as E, getFilters as F, toArray as G, UPDATE_SELECTED_FILTERS as H, UPDATE_SEARCH_TERM as I, UPDATE_PAGE_SIZE as J, UPDATE_PAGE_INDEX as K, SET_SEARCH_ENTRIES as L, SET_ROUTE_FILTERS as M, LOAD_FILTERS_COMPLETE as N, LOAD_FILTERS_ERROR as O, LOAD_FILTERS as P, EXECUTE_SEARCH_ERROR as Q, EXECUTE_SEARCH as R, SET_SEARCH_FILTERS as S, CLEAR_FILTERS as T, UPDATE_SORT_ORDER as U, APPLY_CONFIG as V, actions as W, selectors as X, types as Y, expressions as Z, queries as _, getTabsAndFacets$1 as a, useListing as a0, doSearch as a1, setRouteFilters as a2, searchSagas as a3, triggerListingSsr as a4, triggerMinilistSsr as a5, triggerSearchSsr as a6, routeParams as a7, defaultExpressions as a8, termExpressions as a9, contentTypeIdExpression as aa, filterExpressions as ab, orderByExpression as ac, customWhereExpressions as ad, cloneDeep as ae, getQueryParameter$2 as b, getSelectedFilters as c, getSearchTotalCount$1 as d, getSearchTerm$2 as e, getResults as f, getTotalCount$1 as g, getPageIsLoading$2 as h, getPaging as i, getIsLoading$2 as j, getRenderableFilters$2 as k, getFeaturedResults$2 as l, getFacetTitles$1 as m, getFacetsTotalCount$1 as n, getTabFacets$1 as o, getFacet$1 as p, getCurrentTab$1 as q, getPageIndex$2 as r, getCurrentFacet as s, updateSelectedFilters as t, updateSortOrder$1 as u, updateSearchTerm$1 as v, withMappers as w, updatePageSize$1 as x, updatePageIndex$1 as y, updateCurrentTab$1 as z };
5916
- //# sourceMappingURL=sagas-xJU-zOpn.js.map
6069
+ export { useFacets as $, updateCurrentTab$1 as A, updateCurrentFacet$1 as B, clearFilters$1 as C, selectListing as D, triggerSearch as E, Context as F, getFilters as G, UPDATE_SELECTED_FILTERS as H, UPDATE_SEARCH_TERM as I, UPDATE_PAGE_SIZE as J, UPDATE_PAGE_INDEX as K, SET_SEARCH_ENTRIES as L, SET_ROUTE_FILTERS as M, LOAD_FILTERS_COMPLETE as N, LOAD_FILTERS_ERROR as O, LOAD_FILTERS as P, EXECUTE_SEARCH_ERROR as Q, EXECUTE_SEARCH as R, SET_SEARCH_FILTERS as S, CLEAR_FILTERS as T, UPDATE_SORT_ORDER as U, APPLY_CONFIG as V, actions as W, selectors as X, types as Y, expressions as Z, queries as _, getTabsAndFacets$1 as a, useListing as a0, doSearch as a1, setRouteFilters as a2, searchSagas as a3, triggerListingSsr as a4, triggerMinilistSsr as a5, triggerSearchSsr as a6, defaultExpressions as a7, termExpressions as a8, contentTypeIdExpression as a9, filterExpressions as aa, orderByExpression as ab, customWhereExpressions as ac, cloneDeep as ad, getQueryParameter$2 as b, getSelectedFilters as c, getSearchTotalCount$1 as d, getSearchTerm$2 as e, getResultsInfo as f, getTotalCount$1 as g, getResults as h, getPageIsLoading$2 as i, getPaging as j, getIsLoading$2 as k, getRenderableFilters$2 as l, getFeaturedResults$2 as m, getFacetTitles$1 as n, getFacetsTotalCount$1 as o, getTabFacets$1 as p, getFacet$1 as q, getCurrentTab$1 as r, getPageIndex$2 as s, getCurrentFacet as t, updateSortOrder$1 as u, updateSelectedFilters as v, withMappers as w, updateSearchTerm$1 as x, updatePageSize$1 as y, updatePageIndex$1 as z };
6070
+ //# sourceMappingURL=sagas-Fr9yRduO.js.map