@zengenti/contensis-react-base 3.0.0-beta.6 → 3.0.0-beta.60

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 (164) hide show
  1. package/README.md +4 -4
  2. package/cjs/{App-3324f784.js → App-36c7bf3a.js} +124 -140
  3. package/cjs/App-36c7bf3a.js.map +1 -0
  4. package/cjs/{RouteLoader-c7957b14.js → RouteLoader-ece762dc.js} +31 -23
  5. package/cjs/RouteLoader-ece762dc.js.map +1 -0
  6. package/cjs/ToJs-09204afd.js +129 -0
  7. package/cjs/ToJs-09204afd.js.map +1 -0
  8. package/cjs/VersionInfo-df35c917.js +181 -0
  9. package/cjs/VersionInfo-df35c917.js.map +1 -0
  10. package/cjs/{actions-a24bf46e.js → actions-6b9ef168.js} +5 -4
  11. package/cjs/actions-6b9ef168.js.map +1 -0
  12. package/cjs/client.js +16 -21
  13. package/cjs/client.js.map +1 -1
  14. package/cjs/contensis-react-base.js +3583 -38
  15. package/cjs/contensis-react-base.js.map +1 -1
  16. package/cjs/forms.js +4114 -195
  17. package/cjs/forms.js.map +1 -1
  18. package/cjs/{fromJSLeaveImmer-c00d597f.js → fromJSLeaveImmer-e74c673c.js} +2 -16
  19. package/cjs/fromJSLeaveImmer-e74c673c.js.map +1 -0
  20. package/cjs/{login-c810cc4c.js → login-d67b82aa.js} +92 -55
  21. package/cjs/login-d67b82aa.js.map +1 -0
  22. package/cjs/{reducers-fde41d6b.js → reducers-3a4f8971.js} +26 -25
  23. package/cjs/reducers-3a4f8971.js.map +1 -0
  24. package/cjs/redux.js +6 -5
  25. package/cjs/redux.js.map +1 -1
  26. package/cjs/routing.js +5 -4
  27. package/cjs/routing.js.map +1 -1
  28. package/cjs/sagas-8cf21563.js +2038 -0
  29. package/cjs/sagas-8cf21563.js.map +1 -0
  30. package/cjs/search.js +280 -1907
  31. package/cjs/search.js.map +1 -1
  32. package/cjs/{selectors-0ec95076.js → selectors-2c1b1183.js} +7 -3
  33. package/cjs/selectors-2c1b1183.js.map +1 -0
  34. package/cjs/user.js +21 -12
  35. package/cjs/user.js.map +1 -1
  36. package/cjs/util.js +55 -212
  37. package/cjs/util.js.map +1 -1
  38. package/cjs/{version-4f0f5fa6.js → version-ca4173a8.js} +28 -20
  39. package/cjs/version-ca4173a8.js.map +1 -0
  40. package/cjs/{version-085d203d.js → version-dcfdafd9.js} +5 -5
  41. package/cjs/version-dcfdafd9.js.map +1 -0
  42. package/esm/{App-1b05ab11.js → App-61bf1832.js} +124 -141
  43. package/esm/App-61bf1832.js.map +1 -0
  44. package/esm/{RouteLoader-e5f0e8cb.js → RouteLoader-7749ad3f.js} +31 -23
  45. package/esm/RouteLoader-7749ad3f.js.map +1 -0
  46. package/esm/ToJs-2627ce21.js +99 -0
  47. package/esm/ToJs-2627ce21.js.map +1 -0
  48. package/esm/VersionInfo-add96cdb.js +172 -0
  49. package/esm/VersionInfo-add96cdb.js.map +1 -0
  50. package/esm/{actions-927d9698.js → actions-5437f43d.js} +5 -4
  51. package/esm/actions-5437f43d.js.map +1 -0
  52. package/esm/client.js +17 -22
  53. package/esm/client.js.map +1 -1
  54. package/esm/contensis-react-base.js +3581 -37
  55. package/esm/contensis-react-base.js.map +1 -1
  56. package/esm/forms.js +4114 -198
  57. package/esm/forms.js.map +1 -1
  58. package/esm/{fromJSLeaveImmer-392af4e3.js → fromJSLeaveImmer-0114ffcf.js} +2 -16
  59. package/esm/fromJSLeaveImmer-0114ffcf.js.map +1 -0
  60. package/esm/{login-f8ba3aeb.js → login-f6dfbe1b.js} +92 -55
  61. package/esm/login-f6dfbe1b.js.map +1 -0
  62. package/esm/{reducers-d6c0edb1.js → reducers-8e5d6232.js} +26 -25
  63. package/esm/reducers-8e5d6232.js.map +1 -0
  64. package/esm/redux.js +8 -7
  65. package/esm/redux.js.map +1 -1
  66. package/esm/routing.js +5 -4
  67. package/esm/routing.js.map +1 -1
  68. package/esm/sagas-a22fc54a.js +1952 -0
  69. package/esm/sagas-a22fc54a.js.map +1 -0
  70. package/esm/search.js +240 -1848
  71. package/esm/search.js.map +1 -1
  72. package/esm/{selectors-b98d5c76.js → selectors-65f0f31c.js} +7 -4
  73. package/esm/selectors-65f0f31c.js.map +1 -0
  74. package/esm/user.js +23 -14
  75. package/esm/user.js.map +1 -1
  76. package/esm/util.js +54 -209
  77. package/esm/util.js.map +1 -1
  78. package/esm/{version-16aa83eb.js → version-1d46bde8.js} +27 -20
  79. package/esm/version-1d46bde8.js.map +1 -0
  80. package/esm/version-696796d7.js +15 -0
  81. package/esm/version-696796d7.js.map +1 -0
  82. package/models/app/pages/VersionInfo/components/VersionInfo.d.ts +1 -1
  83. package/models/forms/index.d.ts +2 -0
  84. package/models/index.d.ts +1 -0
  85. package/models/redux/appstate.d.ts +5 -10
  86. package/models/redux/selectors/navigation.d.ts +2 -1
  87. package/models/routing/components/RouteLoader.d.ts +2 -19
  88. package/models/routing/redux/actions.d.ts +1 -1
  89. package/models/routing/redux/selectors.d.ts +1 -1
  90. package/models/routing/routes.d.ts +3 -2
  91. package/models/routing/util/expressions.d.ts +3 -2
  92. package/models/routing/util/queries.d.ts +1 -1
  93. package/models/search/containers/withListing.d.ts +1 -1
  94. package/models/search/containers/withSearch.d.ts +1 -1
  95. package/models/search/hooks/useFacets.hook.d.ts +3 -0
  96. package/models/search/hooks/useListing.hook.d.ts +3 -0
  97. package/models/search/hooks/useMinilist.hook.d.ts +2 -9
  98. package/models/search/index.d.ts +4 -1
  99. package/models/search/models/Queries.d.ts +8 -5
  100. package/models/search/models/Search.d.ts +60 -28
  101. package/models/search/models/SearchActions.d.ts +4 -3
  102. package/models/search/models/SearchProps.d.ts +52 -7
  103. package/models/search/models/SearchState.d.ts +5 -1
  104. package/models/search/models/index.d.ts +3 -1
  105. package/models/search/redux/actions.d.ts +2 -1
  106. package/models/search/redux/reducers.d.ts +230 -314
  107. package/models/search/redux/sagas.d.ts +5 -5
  108. package/models/search/redux/selectors.d.ts +19 -22
  109. package/models/search/search/ContensisDeliveryApi.d.ts +1 -0
  110. package/models/search/search/expressions.d.ts +3 -6
  111. package/models/search/{redux → search}/queries.d.ts +0 -0
  112. package/models/search/transformations/entry-to-filteritem.mapper.d.ts +2 -1
  113. package/models/search/transformations/filter-to-filterexpression.mapper.d.ts +6 -0
  114. package/models/search/transformations/filters-to-filterexpressions.mapper.d.ts +3 -0
  115. package/models/search/transformations/index.d.ts +3 -0
  116. package/models/search/transformations/queryParams-to-customapi.mapper.d.ts +3 -0
  117. package/models/search/transformations/state-to-searchuri.d.ts +2 -13
  118. package/models/server/features/linkdepth-api/api.d.ts +12 -0
  119. package/models/server/features/linkdepth-api/events-api.config.d.ts +37 -0
  120. package/models/server/middleware/bundleManipulation.d.ts +2 -1
  121. package/models/server/util/headers.d.ts +3 -2
  122. package/models/user/components/Login.d.ts +1 -2
  123. package/models/user/components/LoginForm.d.ts +1 -2
  124. package/models/user/hocs/withLogin.d.ts +4 -2
  125. package/models/user/hocs/withRegistration.d.ts +4 -2
  126. package/models/user/hooks/useChangePassword.d.ts +5 -5
  127. package/models/user/hooks/useForgotPassword.d.ts +6 -6
  128. package/models/user/hooks/useLogin.d.ts +9 -45
  129. package/models/user/hooks/useRegistration.d.ts +4 -4
  130. package/models/user/redux/reducers.d.ts +4 -5
  131. package/models/user/redux/sagas/login.d.ts +11 -8
  132. package/models/user/redux/selectors.d.ts +33 -71
  133. package/models/user/util/LoginHelper.class.d.ts +4 -3
  134. package/models/util/ContensisDeliveryApi.d.ts +1 -3
  135. package/models/util/json-mapper.d.ts +9 -3
  136. package/models/util/merge.d.ts +1 -0
  137. package/package-lock.json +2690 -3400
  138. package/package.json +60 -55
  139. package/cjs/App-3324f784.js.map +0 -1
  140. package/cjs/RouteLoader-c7957b14.js.map +0 -1
  141. package/cjs/ToJs-a38fa20e.js +0 -230
  142. package/cjs/ToJs-a38fa20e.js.map +0 -1
  143. package/cjs/actions-a24bf46e.js.map +0 -1
  144. package/cjs/fromJSLeaveImmer-c00d597f.js.map +0 -1
  145. package/cjs/login-c810cc4c.js.map +0 -1
  146. package/cjs/reducers-fde41d6b.js.map +0 -1
  147. package/cjs/selectors-0ec95076.js.map +0 -1
  148. package/cjs/version-085d203d.js.map +0 -1
  149. package/cjs/version-4f0f5fa6.js.map +0 -1
  150. package/esm/App-1b05ab11.js.map +0 -1
  151. package/esm/RouteLoader-e5f0e8cb.js.map +0 -1
  152. package/esm/ToJs-879a5a85.js +0 -199
  153. package/esm/ToJs-879a5a85.js.map +0 -1
  154. package/esm/actions-927d9698.js.map +0 -1
  155. package/esm/fromJSLeaveImmer-392af4e3.js.map +0 -1
  156. package/esm/login-f8ba3aeb.js.map +0 -1
  157. package/esm/reducers-d6c0edb1.js.map +0 -1
  158. package/esm/selectors-b98d5c76.js.map +0 -1
  159. package/esm/version-16aa83eb.js.map +0 -1
  160. package/esm/version-3833e8b5.js +0 -15
  161. package/esm/version-3833e8b5.js.map +0 -1
  162. package/models/search/transformations/filters-to-filterexpression.d.ts +0 -1
  163. package/models/search/transformations/filters-to-filterexpression.mapper.d.ts +0 -2
  164. package/models/server/features/caching/cacheHashing.d.ts +0 -1
package/cjs/search.js CHANGED
@@ -4,46 +4,26 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
6
  var reactRedux = require('react-redux');
7
- var mapJson = require('jsonpath-mapper');
8
- var log = require('loglevel');
9
- var effects = require('@redux-saga/core/effects');
10
- var contensisDeliveryApi = require('contensis-delivery-api');
11
- var queryString = require('query-string');
12
- var contensisCoreApi = require('contensis-core-api');
13
- var merge = require('deepmerge');
7
+ var sagas = require('./sagas-8cf21563.js');
8
+ require('jsonpath-mapper');
14
9
  var reselect = require('reselect');
10
+ var merge = require('deepmerge');
11
+ require('query-string');
12
+ require('contensis-core-api');
15
13
  var immer = require('immer');
16
14
  var equals = require('deep-equal');
15
+ require('loglevel');
16
+ require('@redux-saga/core/effects');
17
+ require('contensis-delivery-api');
17
18
 
18
19
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
19
20
 
20
- function _interopNamespace(e) {
21
- if (e && e.__esModule) return e;
22
- var n = Object.create(null);
23
- if (e) {
24
- Object.keys(e).forEach(function (k) {
25
- if (k !== 'default') {
26
- var d = Object.getOwnPropertyDescriptor(e, k);
27
- Object.defineProperty(n, k, d.get ? d : {
28
- enumerable: true,
29
- get: function () { return e[k]; }
30
- });
31
- }
32
- });
33
- }
34
- n["default"] = e;
35
- return Object.freeze(n);
36
- }
37
-
38
21
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
39
- var mapJson__default = /*#__PURE__*/_interopDefaultLegacy(mapJson);
40
- var log__namespace = /*#__PURE__*/_interopNamespace(log);
41
- var queryString__default = /*#__PURE__*/_interopDefaultLegacy(queryString);
42
22
  var merge__default = /*#__PURE__*/_interopDefaultLegacy(merge);
43
23
  var equals__default = /*#__PURE__*/_interopDefaultLegacy(equals);
44
24
 
45
25
  /* eslint-disable import/default */
46
- const toJS$1 = WrappedComponent => wrappedComponentProps => {
26
+ const toJS = WrappedComponent => wrappedComponentProps => {
47
27
  const KEY = 0;
48
28
  const VALUE = 1;
49
29
  const propsJS = Object.entries(wrappedComponentProps).reduce((newProps, wrappedComponentProp) => {
@@ -55,448 +35,8 @@ const toJS$1 = WrappedComponent => wrappedComponentProps => {
55
35
  return /*#__PURE__*/React__default["default"].createElement(WrappedComponent, propsJS);
56
36
  };
57
37
 
58
- const ACTION_PREFIX = '@SEARCH/';
59
- const APPLY_CONFIG = `${ACTION_PREFIX}APPLY_CONFIG`;
60
- const CLEAR_FILTERS = `${ACTION_PREFIX}CLEAR_FILTERS`;
61
- const DO_SEARCH = `${ACTION_PREFIX}DO_SEARCH`;
62
- const EXECUTE_SEARCH = `${ACTION_PREFIX}EXECUTE_SEARCH`;
63
- const EXECUTE_SEARCH_ERROR = `${ACTION_PREFIX}EXECUTE_SEARCH_ERROR`;
64
- const EXECUTE_SEARCH_PRELOAD = `${ACTION_PREFIX}EXECUTE_SEARCH_PRELOAD`;
65
- const LOAD_FILTERS = `${ACTION_PREFIX}LOAD_FILTERS`;
66
- const LOAD_FILTERS_COMPLETE = `${ACTION_PREFIX}LOAD_FILTERS_COMPLETE`;
67
- const LOAD_FILTERS_ERROR = `${ACTION_PREFIX}LOAD_FILTERS_ERROR`;
68
- const SET_FEATURED_ENTRIES = `${ACTION_PREFIX}SET_FEATURED_ENTRIES`;
69
- const SET_ROUTE_FILTERS = `${ACTION_PREFIX}SET_ROUTE_FILTERS`;
70
- const SET_SEARCH_FILTERS = `${ACTION_PREFIX}SET_SEARCH_FILTERS`;
71
- const SET_SEARCH_ENTRIES = `${ACTION_PREFIX}SET_SEARCH_ENTRIES`;
72
- const SET_SELECTED_FILTER = `${ACTION_PREFIX}SET_SELECTED_FILTER`;
73
- const UPDATE_CURRENT_FACET = `${ACTION_PREFIX}UPDATE_CURRENT_FACET`;
74
- const UPDATE_CURRENT_TAB = `${ACTION_PREFIX}UPDATE_CURRENT_TAB`;
75
- const UPDATE_SORT_ORDER = `${ACTION_PREFIX}UPDATE_SORT_ORDER`;
76
- const UPDATE_PAGE_INDEX = `${ACTION_PREFIX}UPDATE_PAGE_INDEX`;
77
- const UPDATE_SEARCH_TERM = `${ACTION_PREFIX}UPDATE_SEARCH_TERM`;
78
- const UPDATE_SELECTED_FILTERS = `${ACTION_PREFIX}UPDATE_SELECTED_FILTERS`;
79
-
80
- var types = /*#__PURE__*/Object.freeze({
81
- __proto__: null,
82
- APPLY_CONFIG: APPLY_CONFIG,
83
- CLEAR_FILTERS: CLEAR_FILTERS,
84
- DO_SEARCH: DO_SEARCH,
85
- EXECUTE_SEARCH: EXECUTE_SEARCH,
86
- EXECUTE_SEARCH_ERROR: EXECUTE_SEARCH_ERROR,
87
- EXECUTE_SEARCH_PRELOAD: EXECUTE_SEARCH_PRELOAD,
88
- LOAD_FILTERS: LOAD_FILTERS,
89
- LOAD_FILTERS_COMPLETE: LOAD_FILTERS_COMPLETE,
90
- LOAD_FILTERS_ERROR: LOAD_FILTERS_ERROR,
91
- SET_FEATURED_ENTRIES: SET_FEATURED_ENTRIES,
92
- SET_ROUTE_FILTERS: SET_ROUTE_FILTERS,
93
- SET_SEARCH_FILTERS: SET_SEARCH_FILTERS,
94
- SET_SEARCH_ENTRIES: SET_SEARCH_ENTRIES,
95
- SET_SELECTED_FILTER: SET_SELECTED_FILTER,
96
- UPDATE_CURRENT_FACET: UPDATE_CURRENT_FACET,
97
- UPDATE_CURRENT_TAB: UPDATE_CURRENT_TAB,
98
- UPDATE_SORT_ORDER: UPDATE_SORT_ORDER,
99
- UPDATE_PAGE_INDEX: UPDATE_PAGE_INDEX,
100
- UPDATE_SEARCH_TERM: UPDATE_SEARCH_TERM,
101
- UPDATE_SELECTED_FILTERS: UPDATE_SELECTED_FILTERS
102
- });
103
-
104
- const withMappers = (action, mappers) => {
105
- return { ...action,
106
- mappers
107
- };
108
- }; // export const withMappers2 = (actionFunc, args, mappers) => {
109
- // return () => ({ ...actionFunc(args), mappers });
110
- // };
111
-
112
- const triggerSearch = ({
113
- config,
114
- context,
115
- debug,
116
- defaultLang,
117
- excludeIds,
118
- facet,
119
- mapper,
120
- params
121
- }) => {
122
- return {
123
- type: DO_SEARCH,
124
- config,
125
- context,
126
- debug,
127
- defaultLang,
128
- excludeIds,
129
- facet,
130
- mapper,
131
- params
132
- };
133
- };
134
- const initListing = ({
135
- context,
136
- facet,
137
- mapper,
138
- params
139
- }) => {
140
- return {
141
- type: SET_ROUTE_FILTERS,
142
- context,
143
- facet,
144
- mapper,
145
- params
146
- };
147
- };
148
- const navigate = (path, state) => {
149
- return {
150
- type: '@ROUTING/_SET_ROUTE',
151
- path,
152
- state
153
- };
154
- };
155
- const clearFilters$1 = () => {
156
- return {
157
- type: CLEAR_FILTERS
158
- };
159
- };
160
- const updatePageIndex$1 = pageIndex => {
161
- return {
162
- type: UPDATE_PAGE_INDEX,
163
- pageIndex
164
- };
165
- };
166
- const updateCurrentFacet$1 = facet => {
167
- return {
168
- type: UPDATE_CURRENT_FACET,
169
- facet
170
- };
171
- };
172
- const updateCurrentTab$1 = id => {
173
- return {
174
- type: UPDATE_CURRENT_TAB,
175
- id
176
- };
177
- };
178
- const updateSearchTerm$1 = term => {
179
- return {
180
- type: UPDATE_SEARCH_TERM,
181
- term
182
- };
183
- };
184
- const updateSelectedFilters = (filter, key) => {
185
- return {
186
- type: UPDATE_SELECTED_FILTERS,
187
- filter,
188
- key
189
- };
190
- };
191
- const updateSortOrder$1 = (orderBy, facet) => {
192
- return {
193
- type: UPDATE_SORT_ORDER,
194
- orderBy,
195
- facet
196
- };
197
- };
198
-
199
- var actions = /*#__PURE__*/Object.freeze({
200
- __proto__: null,
201
- withMappers: withMappers,
202
- triggerSearch: triggerSearch,
203
- initListing: initListing,
204
- navigate: navigate,
205
- clearFilters: clearFilters$1,
206
- updatePageIndex: updatePageIndex$1,
207
- updateCurrentFacet: updateCurrentFacet$1,
208
- updateCurrentTab: updateCurrentTab$1,
209
- updateSearchTerm: updateSearchTerm$1,
210
- updateSelectedFilters: updateSelectedFilters,
211
- updateSortOrder: updateSortOrder$1
212
- });
213
-
214
- let Context$1; // export type Context = 'facets' | 'listings' | 'minilist';
215
-
216
- (function (Context) {
217
- Context["facets"] = "facets";
218
- Context["listings"] = "listings";
219
- Context["minilist"] = "minilist";
220
- })(Context$1 || (Context$1 = {}));
221
-
222
- // or replace with a stub function for non-immutable gets
223
-
224
- const makeFromJS = (returnType = globalThis.STATE_TYPE || 'immutable') => {
225
- var _immutable, _immutable2;
226
-
227
- return returnType === 'immutable' ? ((_immutable = globalThis.immutable) === null || _immutable === void 0 ? void 0 : _immutable.fromJSOrdered) || ((_immutable2 = globalThis.immutable) === null || _immutable2 === void 0 ? void 0 : _immutable2.fromJS) || (v => v) : v => v;
228
- };
229
-
230
- const getImmutableOrJS = (state, stateKey, fallbackValue, returnType = globalThis.STATE_TYPE || 'immutable') => {
231
- // Find a fromJS function from global that is dynamically loaded in createStore
232
- // or replace with a stub function for non-immutable gets
233
- const fromJS = makeFromJS(returnType);
234
-
235
- if (state && 'get' in state && typeof state.get === 'function' && 'getIn' in state && typeof state.getIn === 'function' && 'toJS' in state && typeof state.toJS === 'function') {
236
- if (Array.isArray(stateKey)) return fromJS(state.getIn(stateKey, fallbackValue));
237
- return fromJS(state.get(stateKey, fallbackValue));
238
- }
239
-
240
- if (Array.isArray(stateKey) && state && typeof state === 'object') {
241
- const result = mapJson.jpath(stateKey.join('.'), state);
242
- if (typeof result === 'undefined') return fallbackValue;
243
- return result;
244
- }
245
-
246
- const result = state && typeof state === 'object' ? state[stateKey] : undefined;
247
- if (typeof result === 'undefined') return fallbackValue;
248
- return result;
249
- };
250
-
251
- const getSearchContext = state => getImmutableOrJS(state, ['search', 'context'], Context$1.facets);
252
- const getCurrent = (state, context = Context$1.facets) => context === Context$1.facets ? getCurrentFacet(state) : getCurrentListing(state);
253
- const getCurrentFacet = state => getImmutableOrJS(state, ['search', 'currentFacet']);
254
- const getCurrentListing = state => getImmutableOrJS(state, ['search', 'currentListing']);
255
- const getCurrentTab = state => getImmutableOrJS(state, ['search', Context$1.facets, getCurrentFacet(state), 'tabId'], 0);
256
- const getFacets = (state, returnType) => getImmutableOrJS(state, ['search', Context$1.facets], {}, returnType);
257
- const getTabFacets = state => Object.fromEntries(Object.entries(getFacets(state, 'js')).filter(([key]) => getImmutableOrJS(getFacets(state), [key, 'tabId'], 0) === getCurrentTab(state)));
258
- const getFacetTitles = state => Object.entries(getFacets(state, 'js')).map(([key, facet = {}]) => {
259
- var _facet$pagingInfo;
260
-
261
- return {
262
- key,
263
- title: facet.title,
264
- totalCount: (_facet$pagingInfo = facet.pagingInfo) === null || _facet$pagingInfo === void 0 ? void 0 : _facet$pagingInfo.totalCount
265
- };
266
- });
267
- const getFacet = (state, facetName = '', context = Context$1.facets, returnType) => {
268
- const currentFacet = facetName || getCurrentFacet(state);
269
- return getImmutableOrJS(state, ['search', context, currentFacet], {}, returnType);
270
- };
271
- const getListing = (state, listing = '') => {
272
- const currentListing = listing || getCurrentListing(state);
273
- return getImmutableOrJS(state, ['search', Context$1.listings, currentListing], {});
274
- };
275
- const getFilters = (state, facet, context = Context$1.facets, returnType) => {
276
- return getImmutableOrJS(state, ['search', context, facet || getCurrent(state, context), 'filters'], {}, returnType);
277
- };
278
- const getRenderableFilters = (state, facet = '', context = Context$1.facets) => Object.fromEntries(Object.entries(getFilters(state, facet, context, 'js')).filter(([, f = {}]) => typeof f.renderable !== 'boolean' ? true : f.renderable));
279
- const getFiltersToLoad = (state, facet, context = Context$1.facets, returnType) => {
280
- const filters = getFilters(state, facet, context, returnType);
281
- const loadedFilters = Object.entries(filters).map(([key, f = {}]) => [key, (f.items || []).filter(i => {
282
- const title = i === null || i === void 0 ? void 0 : i.title;
283
- return typeof title !== 'undefined' && !!title;
284
- }).length > 0 && (f.isError || false) === false]);
285
- return loadedFilters.map(([filterKey, isLoaded]) => !isLoaded ? filterKey : null).filter(f => !!f);
286
- }; // We lowercase the filter key unless it's an ISO date string where the T must be uppercase
287
-
288
- const getSelectedFilters = (state, facet = '', context = Context$1.facets, returnType) => {
289
- const filters = getFilters(state, facet, context, 'js');
290
- const isoDateRegex = RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d/);
291
- const selectedFilters = Object.fromEntries(Object.entries(filters).map(([key, filter = {}]) => [key, (filter.items || []).filter(item => !!(item.isSelected || false)).map(item => {
292
- const key = (item === null || item === void 0 ? void 0 : item.key) || '';
293
- const isIsoDate = isoDateRegex.test(key);
294
- return isIsoDate ? key : key.toLowerCase();
295
- })]));
296
- const fromJS = makeFromJS(returnType);
297
- return fromJS(selectedFilters);
298
- };
299
- const getResults = (state, current = '', context = Context$1.facets, returnType) => {
300
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'results'], [], returnType);
301
- };
302
- const getIsInternalPaging = (state, current, context = Context$1.facets) => {
303
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'queryParams', 'internalPaging'], false);
304
- };
305
- const getIsLoaded = (state, context = Context$1.facets, facet) => {
306
- return !!getImmutableOrJS(state, ['search', context, facet || getCurrent(state, context), 'queryDuration'], 0);
307
- };
308
- const getIsLoading = (state, context = Context$1.facets, facet) => {
309
- return getImmutableOrJS(state, ['search', context, facet || getCurrent(state, context), 'entries', 'isLoading']);
310
- };
311
- const getIsSsr = state => getImmutableOrJS(state, ['search', 'config', 'ssr'], false);
312
- const getFeaturedResults = (state, current = '', context = Context$1.facets) => {
313
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'featuredResults'], []);
314
- };
315
- const getPaging = (state, current = '', context = Context$1.facets, returnType) => {
316
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'pagingInfo'], {}, returnType);
317
- };
318
- const getPageIndex = (state, current = '', context = Context$1.facets) => {
319
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'pagingInfo', 'pageIndex']);
320
- };
321
- const getPrevPageIndex = (state, current = '', context = Context$1.facets) => {
322
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'pagingInfo', 'prevPageIndex']);
323
- };
324
- const getPageIsLoading = (state, current = '', context = Context$1.facets) => {
325
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'pagingInfo', 'isLoading']);
326
- };
327
- const getPagesLoaded = (state, current = '', context = Context$1.facets) => {
328
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'pagingInfo', 'pagesLoaded'], [], 'js');
329
- };
330
- const getTotalCount = (state, current = '', context = Context$1.facets) => {
331
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'pagingInfo', 'totalCount']);
332
- };
333
- const getSearchTerm = state => getImmutableOrJS(state, ['search', 'term']);
334
- const getSearchTabs = (state, returnType) => getImmutableOrJS(state, ['search', 'tabs'], [], returnType);
335
- const getQueryParams = (state, current = '', context = Context$1.facets) => {
336
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'queryParams'], {}, 'js');
337
- };
338
- const getQueryParameter = ({
339
- state,
340
- facet,
341
- context = Context$1.facets
342
- }, key, ifnull = null) => {
343
- return getImmutableOrJS(getQueryParams(state, facet, context), key, ifnull, 'js');
344
- };
345
- const getCustomApi = (state, current, context = Context$1.facets, returnType) => {
346
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'customApi'], null, returnType);
347
- };
348
- const getCustomEnv = (state, current, context = Context$1.facets) => {
349
- return getImmutableOrJS(state, ['search', context, current || getCurrent(state, context), 'env']);
350
- };
351
- const getTabsAndFacets = (state, returnType) => {
352
- const tabs = getSearchTabs(state, 'js');
353
- const facets = getFacets(state, 'js');
354
- const tabsAndFacets = (tabs || []).map((tab = {}) => {
355
- const fieldsToCount = tab.totalCount;
356
- let countFields;
357
- if (typeof fieldsToCount === 'string') countFields = [[fieldsToCount]];
358
- const thisTabFacets = Object.entries(facets).filter(([key]) => getImmutableOrJS(facets, [key, 'tabId'], 0) === tab.id);
359
- const thisTabTotal = thisTabFacets.map(([facetName, facet = {}]) => {
360
- if (!countFields || countFields.find((f = []) => (f === null || f === void 0 ? void 0 : f[0]) === facetName)) return getImmutableOrJS(facet, ['pagingInfo', 'totalCount']);
361
- return 0;
362
- }).reduce((a, b) => a + b, 0);
363
- return { ...tab,
364
- [Context$1.facets]: Object.fromEntries(thisTabFacets),
365
- totalCount: thisTabTotal
366
- };
367
- });
368
- const fromJS = makeFromJS(returnType);
369
- return fromJS(tabsAndFacets);
370
- };
371
- const getSearchTotalCount = state => {
372
- const tabsAndFacets = getTabsAndFacets(state, 'js');
373
- const wholeSearchTotal = tabsAndFacets.map((t = {}) => t.totalCount).reduce((a, b) => a + b, 0);
374
- return wholeSearchTotal;
375
- };
376
- const getFacetsTotalCount = state => {
377
- const facets = getFacets(state);
378
- const wholeSearchTotal = Object.entries(facets).map(([, t = {}]) => {
379
- var _t$pagingInfo;
380
-
381
- return ((_t$pagingInfo = t.pagingInfo) === null || _t$pagingInfo === void 0 ? void 0 : _t$pagingInfo.totalCount) || 0;
382
- }).reduce((a, b) => a + b, 0);
383
- return wholeSearchTotal;
384
- }; // An exported copy of the relevant selectors scoped by default to a facets context
385
-
386
- const selectFacets = {
387
- getCurrent: getCurrentFacet,
388
- getCurrentTab,
389
- getCustomApi,
390
- getCustomEnv,
391
- getFacet,
392
- getFacetTitles,
393
- getFacets,
394
- getFacetsTotalCount,
395
- getFeaturedResults,
396
- getFilters,
397
- getFiltersToLoad,
398
- getIsLoaded,
399
- getIsLoading,
400
- getPageIndex,
401
- getPageIsLoading,
402
- getPagesLoaded,
403
- getPaging,
404
- getQueryParams: (state, facet) => getQueryParams(state, facet, Context$1.facets),
405
- getQueryParameter: ({
406
- state,
407
- facet
408
- }, key, ifnull) => getQueryParameter({
409
- state,
410
- facet,
411
- context: Context$1.facets
412
- }, key, ifnull),
413
- getRenderableFilters,
414
- getResults,
415
- getTabFacets,
416
- getTabsAndFacets,
417
- getTotalCount,
418
- getSearchTabs,
419
- getSearchTerm,
420
- getSearchTotalCount,
421
- getSelectedFilters
422
- }; // An exported copy of the relevant selectors pre-scoped to a listing context
423
-
424
- const selectListing = {
425
- getCurrent: getCurrentListing,
426
- getFeaturedResults: (state, listing = '') => getFeaturedResults(state, listing, Context$1.listings),
427
- getFilters: (state, listing = '') => getFilters(state, listing, Context$1.listings),
428
- getFiltersToLoad: (state, listing = '') => getFiltersToLoad(state, listing, Context$1.listings),
429
- getListing,
430
- getIsLoaded: state => getIsLoaded(state, Context$1.listings),
431
- getIsLoading: state => getIsLoading(state, Context$1.listings),
432
- getPageIndex: (state, listing = '') => getPageIndex(state, listing, Context$1.listings),
433
- getPaging: (state, listing = '') => getPaging(state, listing, Context$1.listings),
434
- getPageIsLoading: (state, listing = '') => getPageIsLoading(state, listing, Context$1.listings),
435
- getPagesLoaded: (state, listing = '') => getPagesLoaded(state, listing, Context$1.listings),
436
- getQueryParams: (state, listing = '') => getQueryParams(state, listing, Context$1.listings),
437
- getQueryParameter: ({
438
- state,
439
- facet
440
- }, key, ifnull) => getQueryParameter({
441
- state,
442
- facet,
443
- context: Context$1.listings
444
- }, key, ifnull),
445
- getRenderableFilters: (state, listing = '') => getRenderableFilters(state, listing, Context$1.listings),
446
- getResults: (state, listing = '') => getResults(state, listing, Context$1.listings),
447
- getSearchTerm,
448
- getTotalCount: (state, listing = '') => getTotalCount(state, listing, Context$1.listings),
449
- getSelectedFilters: (state, listing = '') => getSelectedFilters(state, listing, Context$1.listings)
450
- };
451
- const selectCurrentPath = state => getImmutableOrJS(state, ['routing', 'currentPath']);
452
- const selectVersionStatus = state => getImmutableOrJS(state, ['version', 'contensisVersionStatus']);
453
-
454
- var selectors = /*#__PURE__*/Object.freeze({
455
- __proto__: null,
456
- getSearchContext: getSearchContext,
457
- getCurrent: getCurrent,
458
- getCurrentFacet: getCurrentFacet,
459
- getCurrentListing: getCurrentListing,
460
- getCurrentTab: getCurrentTab,
461
- getFacets: getFacets,
462
- getTabFacets: getTabFacets,
463
- getFacetTitles: getFacetTitles,
464
- getFacet: getFacet,
465
- getListing: getListing,
466
- getFilters: getFilters,
467
- getRenderableFilters: getRenderableFilters,
468
- getFiltersToLoad: getFiltersToLoad,
469
- getSelectedFilters: getSelectedFilters,
470
- getResults: getResults,
471
- getIsInternalPaging: getIsInternalPaging,
472
- getIsLoaded: getIsLoaded,
473
- getIsLoading: getIsLoading,
474
- getIsSsr: getIsSsr,
475
- getFeaturedResults: getFeaturedResults,
476
- getPaging: getPaging,
477
- getPageIndex: getPageIndex,
478
- getPrevPageIndex: getPrevPageIndex,
479
- getPageIsLoading: getPageIsLoading,
480
- getPagesLoaded: getPagesLoaded,
481
- getTotalCount: getTotalCount,
482
- getSearchTerm: getSearchTerm,
483
- getSearchTabs: getSearchTabs,
484
- getQueryParams: getQueryParams,
485
- getQueryParameter: getQueryParameter,
486
- getCustomApi: getCustomApi,
487
- getCustomEnv: getCustomEnv,
488
- getTabsAndFacets: getTabsAndFacets,
489
- getSearchTotalCount: getSearchTotalCount,
490
- getFacetsTotalCount: getFacetsTotalCount,
491
- selectFacets: selectFacets,
492
- selectListing: selectListing,
493
- selectCurrentPath: selectCurrentPath,
494
- selectVersionStatus: selectVersionStatus
495
- });
496
-
497
38
  // eslint-disable-next-line import/default
498
39
 
499
- /* eslint-disable @typescript-eslint/naming-convention */
500
40
  const withSearch = mappers => SearchComponent => {
501
41
  const Wrapper = props => {
502
42
  return /*#__PURE__*/React__default["default"].createElement(SearchComponent, props);
@@ -506,41 +46,42 @@ const withSearch = mappers => SearchComponent => {
506
46
 
507
47
  const mapStateToProps = state => {
508
48
  return {
509
- currentFacet: getCurrentFacet(state),
510
- currentPageIndex: getPageIndex(state),
511
- currentTabIndex: getCurrentTab(state),
512
- facet: getFacet(state),
513
- facets: getTabFacets(state),
514
- facetsTotalCount: getFacetsTotalCount(state),
515
- facetTitles: getFacetTitles(state),
516
- featuredResults: getFeaturedResults(state),
517
- filters: getRenderableFilters(state),
518
- isLoading: getIsLoading(state),
519
- paging: getPaging(state),
520
- pageIsLoading: getPageIsLoading(state),
521
- results: getResults(state),
49
+ currentFacet: sagas.getCurrentFacet(state),
50
+ currentPageIndex: sagas.getPageIndex(state),
51
+ currentTabIndex: sagas.getCurrentTab(state),
52
+ facet: sagas.getFacet(state),
53
+ facets: sagas.getTabFacets(state),
54
+ facetsTotalCount: sagas.getFacetsTotalCount(state),
55
+ facetTitles: sagas.getFacetTitles(state),
56
+ featuredResults: sagas.getFeaturedResults(state),
57
+ filters: sagas.getRenderableFilters(state),
58
+ isLoading: sagas.getIsLoading(state),
59
+ paging: sagas.getPaging(state),
60
+ pageIsLoading: sagas.getPageIsLoading(state),
61
+ results: sagas.getResults(state),
522
62
  resultsInfo: (mappers === null || mappers === void 0 ? void 0 : mappers.resultsInfo) && mappers.resultsInfo(state),
523
- searchTerm: getSearchTerm(state),
524
- searchTotalCount: getSearchTotalCount(state),
525
- sortOrder: getQueryParameter({
63
+ searchTerm: sagas.getSearchTerm(state),
64
+ searchTotalCount: sagas.getSearchTotalCount(state),
65
+ selectedFilters: sagas.getSelectedFilters(state),
66
+ sortOrder: sagas.getQueryParameter({
526
67
  state
527
68
  }, 'dynamicOrderBy', []),
528
- tabsAndFacets: getTabsAndFacets(state),
529
- totalCount: getTotalCount(state)
69
+ tabsAndFacets: sagas.getTabsAndFacets(state),
70
+ totalCount: sagas.getTotalCount(state)
530
71
  };
531
72
  };
532
73
 
533
74
  const mapDispatchToProps = {
534
- clearFilters: () => withMappers(clearFilters$1(), mappers),
535
- updateCurrentFacet: facet => withMappers(updateCurrentFacet$1(facet), mappers),
536
- updateCurrentTab: id => withMappers(updateCurrentTab$1(id), mappers),
537
- updatePageIndex: pageIndex => withMappers(updatePageIndex$1(pageIndex), mappers),
538
- updateSearchTerm: term => withMappers(updateSearchTerm$1(term), mappers),
539
- updateSelectedFilters: (filter, key) => withMappers(updateSelectedFilters(filter, key), mappers),
540
- updateSortOrder: orderBy => withMappers(updateSortOrder$1(orderBy), mappers)
75
+ clearFilters: () => sagas.withMappers(sagas.clearFilters(), mappers),
76
+ updateCurrentFacet: facet => sagas.withMappers(sagas.updateCurrentFacet(facet), mappers),
77
+ updateCurrentTab: id => sagas.withMappers(sagas.updateCurrentTab(id), mappers),
78
+ updatePageIndex: pageIndex => sagas.withMappers(sagas.updatePageIndex(pageIndex), mappers),
79
+ updateSearchTerm: term => sagas.withMappers(sagas.updateSearchTerm(term), mappers),
80
+ updateSelectedFilters: (filter, key, isUnknownItem = false) => sagas.withMappers(sagas.updateSelectedFilters(filter, key, isUnknownItem), mappers),
81
+ updateSortOrder: orderBy => sagas.withMappers(sagas.updateSortOrder(orderBy), mappers)
541
82
  };
542
83
  const connector = reactRedux.connect(mapStateToProps, mapDispatchToProps);
543
- return connector(toJS$1(Wrapper));
84
+ return connector(toJS(Wrapper));
544
85
  };
545
86
 
546
87
  /* eslint-disable @typescript-eslint/naming-convention */
@@ -562,7 +103,7 @@ const withListing = mappers => ListingComponent => {
562
103
  getRenderableFilters,
563
104
  getResults,
564
105
  getSearchTerm
565
- } = selectListing;
106
+ } = sagas.selectListing;
566
107
 
567
108
  const mapStateToProps = state => {
568
109
  return {
@@ -576,6 +117,7 @@ const withListing = mappers => ListingComponent => {
576
117
  results: getResults(state),
577
118
  resultsInfo: mappers && typeof mappers.resultsInfo === 'function' && mappers.resultsInfo(state),
578
119
  searchTerm: getSearchTerm(state),
120
+ selectedFilters: sagas.getSelectedFilters(state),
579
121
  sortOrder: getQueryParameter({
580
122
  state
581
123
  }, 'dynamicOrderBy', [])
@@ -583,1399 +125,216 @@ const withListing = mappers => ListingComponent => {
583
125
  };
584
126
 
585
127
  const mapDispatchToProps = {
586
- clearFilters: () => withMappers(clearFilters$1(), mappers),
587
- updateCurrentFacet: facet => withMappers(updateCurrentFacet$1(facet), mappers),
588
- updatePageIndex: pageIndex => withMappers(updatePageIndex$1(pageIndex), mappers),
589
- updateSearchTerm: term => withMappers(updateSearchTerm$1(term), mappers),
590
- updateSelectedFilters: (filter, key) => withMappers(updateSelectedFilters(filter, key), mappers),
591
- updateSortOrder: orderBy => withMappers(updateSortOrder$1(orderBy), mappers)
592
- };
593
- return reactRedux.connect(mapStateToProps, mapDispatchToProps)(toJS$1(Wrapper));
594
- };
595
-
596
- const getClientConfig = (project, env) => {
597
- let config = DELIVERY_API_CONFIG;
598
- /* global DELIVERY_API_CONFIG */
599
-
600
- if (project) {
601
- config.projectId = project;
602
- }
603
-
604
- if (typeof window != 'undefined' && PROXY_DELIVERY_API
605
- /* global PROXY_DELIVERY_API */
606
- ) {
607
- // ensure a relative url is used to bypass the need for CORS (separate OPTIONS calls)
608
- config.rootUrl = env || '';
609
- config.responseHandler = {
610
- 404: () => null
611
- };
612
- }
613
-
614
- return config;
615
- };
616
-
617
- class CacheNode {
618
- constructor(key, value) {
619
- this.key = key;
620
- this.value = value;
621
- this.next = null;
622
- this.prev = null;
623
- }
624
-
625
- }
626
-
627
- class LruCache {
628
- constructor(limit = 100) {
629
- this.map = {};
630
- this.head = null;
631
- this.tail = null;
632
- this.limit = limit || 100;
633
- this.size = 0;
634
- }
635
-
636
- get(key) {
637
- if (this.map[key]) {
638
- let value = this.map[key].value;
639
- let node = new CacheNode(key, value);
640
- this.remove(key);
641
- this.setHead(node);
642
- return value;
643
- }
644
- }
645
-
646
- set(key, value) {
647
- let node = new CacheNode(key, value);
648
-
649
- if (this.map[key]) {
650
- this.remove(key);
651
- } else {
652
- if (this.size >= this.limit) {
653
- delete this.map[this.tail.key];
654
- this.size--;
655
- this.tail = this.tail.prev;
656
- this.tail.next = null;
657
- }
658
- }
659
-
660
- this.setHead(node);
661
- }
662
-
663
- setHead(node) {
664
- node.next = this.head;
665
- node.prev = null;
666
-
667
- if (this.head) {
668
- this.head.prev = node;
669
- }
670
-
671
- this.head = node;
672
-
673
- if (!this.tail) {
674
- this.tail = node;
675
- }
676
-
677
- this.size++;
678
- this.map[node.key] = node;
679
- }
680
-
681
- remove(key) {
682
- let node = this.map[key];
683
-
684
- if (node.prev) {
685
- node.prev.next = node.next;
686
- } else {
687
- this.head = node.next;
688
- }
689
-
690
- if (node.next) {
691
- node.next.prev = node.prev;
692
- } else {
693
- this.tail = node.prev;
694
- }
695
-
696
- delete this.map[key];
697
- this.size--;
698
- }
699
-
700
- }
701
-
702
- class CachedSearch {
703
- constructor() {
704
- this.cache = new LruCache();
705
- this.taxonomyLookup = {};
706
- }
707
-
708
- search(query, linkDepth, project, env) {
709
- const client = contensisDeliveryApi.Client.create(getClientConfig(project, env));
710
- return this.request(project + JSON.stringify(query) + linkDepth.toString(), () => client.entries.search(query, linkDepth));
711
- }
712
-
713
- getTaxonomyNodeByPath(path, project, env) {
714
- const client = contensisDeliveryApi.Client.create(getClientConfig(project, env));
715
- return this.request(`[TAXONOMY NODE] ${path}`, () => client.taxonomy.getNodeByPath({
716
- path: path,
717
- order: 'defined',
718
- childDepth: 2
719
- }).then(node => this.extendTaxonomyNode(node)));
720
- }
721
-
722
- request(key, execute) {
723
- if (!this.cache.get(key) || typeof window == 'undefined') {
724
- let promise = execute();
725
- this.cache.set(key, promise);
726
- promise.catch(() => {
727
- this.cache.remove(key);
728
- });
729
- }
730
-
731
- return this.cache.get(key);
732
- }
733
-
734
- extendTaxonomyNode(node) {
735
- let id = this.getTaxonomyId(node);
736
- this.taxonomyLookup[id] = node.key;
737
- return { ...node,
738
- id,
739
- children: node.children ? node.children.map(n => this.extendTaxonomyNode(n)) : null
740
- };
741
- }
742
-
743
- getTaxonomyId(node) {
744
- if (node.key) {
745
- let parts = node.key.split('/');
746
- return parts[parts.length - 1];
747
- }
748
-
749
- return '';
750
- }
751
-
752
- }
753
-
754
- const cachedSearch = new CachedSearch();
755
-
756
- const now = () => {
757
- if (typeof window == 'undefined') {
758
- return Date.now();
759
- }
760
-
761
- return window.performance.now();
762
- };
763
-
764
- // eslint-disable-next-line import/default
765
- function fixFreeTextForElastic(s) {
766
- const illegalChars = ['>', '<', '=', '|', '!', '{', '}', '[', ']', '^', '~', '*', '?', ':', '\\', '/'];
767
- const illegalRegEx = new RegExp(illegalChars.map(c => '\\' + c).join('|'), 'g');
768
- s = s.replace(illegalRegEx, ''); // s = s.replace(encodedRegEx, ''); // (m) => '\\\\' + m);
769
-
770
- return s;
771
- }
772
- const timedSearch = async (query, linkDepth = 0, projectId, env) => {
773
- if (!query) return null;
774
- let duration = 0;
775
- const start = now();
776
- const payload = await cachedSearch.search(query, linkDepth, projectId, env);
777
- const end = now();
778
- duration = end - start;
779
- return {
780
- duration,
781
- payload
128
+ clearFilters: () => sagas.withMappers(sagas.clearFilters(), mappers),
129
+ updateCurrentFacet: facet => sagas.withMappers(sagas.updateCurrentFacet(facet), mappers),
130
+ updatePageIndex: pageIndex => sagas.withMappers(sagas.updatePageIndex(pageIndex), mappers),
131
+ updateSearchTerm: term => sagas.withMappers(sagas.updateSearchTerm(term), mappers),
132
+ updateSelectedFilters: (filter, key, isUnknownItem = false) => sagas.withMappers(sagas.updateSelectedFilters(filter, key, isUnknownItem), mappers),
133
+ updateSortOrder: orderBy => sagas.withMappers(sagas.updateSortOrder(orderBy), mappers)
782
134
  };
135
+ return reactRedux.connect(mapStateToProps, mapDispatchToProps)(toJS(Wrapper));
783
136
  };
784
- const getItemsFromResult = result => {
785
- const {
786
- payload
787
- } = result || {};
788
-
789
- if (payload) {
790
- if (Array.isArray(payload)) return payload;
791
- if (Array.isArray(payload.items)) return payload.items;
792
- return payload;
793
- }
794
-
795
- return [];
796
- };
797
- const extractQuotedPhrases = searchTerm => {
798
- const pattern = new RegExp(/(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')/gm);
799
- return (searchTerm.match(pattern) || []).map(match => match.replace(/"/g, ''));
800
- };
801
- const buildUrl = (route, params) => {
802
- const qs = queryString__default["default"].stringify(params);
803
- const path = qs ? `${route}?${qs}` : route;
804
- return path;
805
- };
806
- const callCustomApi = async (customApi, filters) => {
807
- const apiUri = customApi.uri || '';
808
- let uri = buildUrl(apiUri, filters);
809
- if (!uri) throw new Error('uri is required to use customApi');
810
- if (typeof window == 'undefined' && uri.startsWith('/')) uri = `http://localhost:3001${uri}`;
811
- const response = await fetch(uri);
812
- return await response.json();
813
- };
814
- const removeEmptyAttributes = obj => {
815
- Object.entries(obj).forEach(([key, val]) => val && typeof val === 'object' && removeEmptyAttributes(val) || (typeof val === 'undefined' || val === null || val === '') && delete obj[key]);
816
- return obj;
817
- };
818
- const toArray = (obj, seperator = ',') => typeof obj === 'undefined' || obj === null ? obj : Array.isArray(obj) ? obj : obj.split(seperator); // assumes array elements are primitive types
819
-
820
- const areArraysEqualSets = (a1, a2) => {
821
- const superSet = {};
822
-
823
- for (const ai of a1) {
824
- const e = ai + typeof ai;
825
- superSet[e] = 1;
826
- }
827
-
828
- for (const ai of a2) {
829
- const e = ai + typeof ai;
830
-
831
- if (!superSet[e]) {
832
- return false;
833
- }
834
-
835
- superSet[e] = 2;
836
- }
837
-
838
- for (const e in superSet) {
839
- if (superSet[e] === 1) {
840
- return false;
841
- }
842
- }
843
137
 
844
- return true;
138
+ var defaultMappers = {
139
+ results: entries => entries,
140
+ navigate: sagas.mapStateToSearchUri
845
141
  };
846
142
 
847
- const DataFormats = {
848
- asset: 'asset',
849
- entry: 'entry',
850
- webpage: 'webpage'
851
- };
852
- const FilterExpressionTypes = {
853
- contentType: 'contentType',
854
- field: 'field'
855
- };
856
- const sys = {
857
- allUris: 'sys.allUris',
858
- contentTypeId: 'sys.contentTypeId',
859
- dataFormat: 'sys.dataFormat',
860
- filename: 'sys.properties.filename',
861
- id: 'sys.id',
862
- includeInSearch: 'sys.metadata.includeInSearch',
863
- language: 'sys.language',
864
- uri: 'sys.uri',
865
- versionStatus: 'sys.versionStatus'
866
- };
867
- const Fields = {
868
- entryDescription: 'entryDescription',
869
- entryTitle: 'entryTitle',
870
- keywords: 'keywords',
871
- searchContent: 'searchContent',
872
- sys,
873
- contentTypeId: 'sys.contentTypeId',
874
- wildcard: '*'
875
- };
876
-
877
- const fieldExpression = (field, value, operator = 'equalTo', weight) => {
878
- if (!field || !value) return [];
879
- if (Array.isArray(field)) // If an array of fieldIds have been provided, call self for each fieldId
880
- // to generate expressions that are combined with an 'or' operator
881
- return [contensisCoreApi.Op.or(...field.map(fieldId => fieldExpression(fieldId, value, operator, weight)).flat())];
882
- if (operator === 'between') return between(field, value);
883
- if (Array.isArray(value)) return equalToOrIn(field, value, operator);else return !weight ? [contensisCoreApi.Op[operator](field, value, undefined, undefined)] : [contensisCoreApi.Op[operator](field, value, undefined, undefined).weight(weight)];
884
- };
885
- const contentTypeIdExpression = (contentTypeIds, webpageTemplates, assetTypes) => {
886
- const expressions = [];
887
- if (!contentTypeIds && !webpageTemplates && !assetTypes) return expressions;
888
-
889
- if (contentTypeIds && contentTypeIds.length > 0) {
890
- expressions.push(...dataFormatExpression(contentTypeIds, DataFormats.entry));
891
- }
892
-
893
- if (webpageTemplates && webpageTemplates.length > 0) {
894
- expressions.push(...dataFormatExpression(webpageTemplates, DataFormats.webpage));
895
- }
896
-
897
- if (assetTypes && assetTypes.length > 0) {
898
- expressions.push(...dataFormatExpression(assetTypes, DataFormats.asset));
899
- }
900
-
901
- if (expressions.length > 1) return [contensisCoreApi.Op.or(...expressions)];
902
- return expressions;
903
- };
904
- const filterExpressions = filters => {
905
- if (!filters) return [];
906
- const expressions = [];
907
- filters.map(param => {
908
- expressions.push(...fieldExpression(param.key, param.value, param.operator || 'in'));
909
- });
910
- return expressions;
911
- };
912
- const dataFormatExpression = (contentTypeIds, dataFormat = DataFormats.entry) => {
913
- if (contentTypeIds && contentTypeIds.length > 0) {
914
- /**
915
- * We have an array of contentTypeIds some may be prefixed with a "!"
916
- * to indicate this is a "not" expression
917
- */
918
- const withContentTypeIds = contentTypeIds.filter(c => !c.startsWith('!'));
919
- const notContentTypeIds = contentTypeIds.filter(c => c.startsWith('!')).map(id => id.substring(1));
920
- const andExpr = contensisCoreApi.Op.and();
921
- const dataFormatExpr = fieldExpression(Fields.sys.dataFormat, dataFormat)[0];
922
- const withExpr = fieldExpression(Fields.sys.contentTypeId, withContentTypeIds)[0];
923
- const notExpr = contensisCoreApi.Op.not(fieldExpression(Fields.sys.contentTypeId, notContentTypeIds)[0]);
924
- andExpr.add(dataFormatExpr);
925
- if (withContentTypeIds.length > 0) andExpr.add(withExpr);
926
- if (notContentTypeIds.length > 0) andExpr.add(notExpr);
927
- return [andExpr];
928
- }
929
-
930
- return [];
931
- };
932
- const featuredResultsExpression = ({
933
- contentTypeId,
934
- fieldId,
935
- fieldValue = true
936
- } = {}) => {
937
- const expressions = [];
938
-
939
- if (contentTypeId) {
940
- expressions.push(...contentTypeIdExpression(Array.isArray(contentTypeId) ? contentTypeId : [contentTypeId]));
941
- }
942
-
943
- if (fieldId && fieldValue) {
944
- expressions.push(...fieldExpression(fieldId, fieldValue));
945
- }
946
-
947
- return expressions;
948
- };
949
- const languagesExpression = languages => fieldExpression(Fields.sys.language, languages);
950
- const includeInSearchExpressions = (webpageTemplates, includeInSearchFields) => {
951
- const expressions = []; // Or include this expression if we have explicity specified non-default includeInSearch fields
952
-
953
- if (Array.isArray(includeInSearchFields)) expressions.push(...includeInSearchFields.map(includeInSearchField => contensisCoreApi.Op.or(contensisCoreApi.Op.and(contensisCoreApi.Op.exists(includeInSearchField, true), contensisCoreApi.Op.equalTo(includeInSearchField, true)), contensisCoreApi.Op.exists(includeInSearchField, false)))); // If webpageTemplates have been specified, include this expression
954
- // with the default includeInSearch field from classic Contensis.
955
-
956
- if (Array.isArray(webpageTemplates) && webpageTemplates.length > 0) expressions.push(contensisCoreApi.Op.or(contensisCoreApi.Op.and(contensisCoreApi.Op.exists(Fields.sys.includeInSearch, true), contensisCoreApi.Op.equalTo(Fields.sys.includeInSearch, true)), contensisCoreApi.Op.exists(Fields.sys.includeInSearch, false)));
957
- return expressions;
958
- };
959
- const defaultExpressions = versionStatus => {
960
- return [contensisCoreApi.Op.equalTo(Fields.sys.versionStatus, versionStatus)];
961
- };
962
- const excludeIdsExpression = excludeIds => {
963
- if (Array.isArray(excludeIds) && excludeIds.length > 0) {
964
- const [expr] = fieldExpression(Fields.sys.id, excludeIds);
965
- return [contensisCoreApi.Op.not(expr)];
966
- } else return [];
967
- };
968
- const orderByExpression = orderBy => {
969
- let expression = contensisCoreApi.OrderBy;
970
-
971
- if (orderBy && orderBy.length > 0) {
972
- orderBy.map(ob => expression = ob.startsWith('-') ? expression.desc(ob.substring(1)) : expression.asc(ob));
973
- }
974
-
975
- return expression;
976
- };
977
-
978
- const equalToOrIn = (field, value, operator = 'equalTo') => {
979
- if (value.length === 0) return [];
980
-
981
- if (Array.isArray(value)) {
982
- if (value.length === 1) return [contensisCoreApi.Op[operator](field, value[0], undefined, undefined)];
983
- return [contensisCoreApi.Op.in(field, ...value)];
984
- }
985
-
986
- return [];
987
- };
988
-
989
- const between = (field, value) => {
990
- const handle = betweenValue => {
991
- const valArr = betweenValue.split('-');
992
-
993
- if (valArr.length > 1) {
994
- const [minimum, maximum = null] = betweenValue.split('-');
995
- return contensisCoreApi.Op.between(field, minimum, maximum);
996
- } else {
997
- // eslint-disable-next-line no-console
998
- 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.`);
999
- return false;
1000
- }
1001
- };
1002
-
1003
- if (value.length === 0) return [];
1004
- if (Array.isArray(value)) return [contensisCoreApi.Op.or(...value.map(handle).filter(bc => bc !== false))]; // const valArr = value.split('-');
1005
-
1006
- const op = handle(value);
1007
- return op ? [op] : []; // valArr.length > 1 ? [Op.between(field, ...value.split('-'))] : [];
1008
- };
1009
- /**
1010
- * Accept HTTP style objects and map them to
1011
- * their equivalent JS client "Op" expressions
1012
- * @param {array} where the where array as you'd provide it to the HTTP API
1013
- * @returns {array} array of constructed Delivery API Operators
1014
- */
1015
-
1016
-
1017
- const customWhereExpressions = where => {
1018
- if (!where || !Array.isArray(where)) return []; // Map each clause inside the where array
1019
-
1020
- return where.map(clause => {
1021
- let expression; // Map through each property in the clause so we can
1022
- // capture the values required and reconstruct them as
1023
- // a Delivery API expression
1024
-
1025
- let operator;
1026
- Object.keys(clause).map((key, idx) => {
1027
- // The clause may contain only one key
1028
- if (idx === 0) operator = key;
1029
- const field = clause.field;
1030
- const value = clause[Object.keys(clause).find(k => !['field', 'weight'].includes(k)) || ''];
1031
- const weight = clause.weight;
1032
-
1033
- if (idx === 0) {
1034
- if (operator === 'and' || operator === 'or') {
1035
- // These are array expressions so we can call ourself recursively
1036
- // to map these inner values to expressions
1037
- const recurseExpr = customWhereExpressions(clause[operator]);
1038
- expression = contensisCoreApi.Op[operator](...recurseExpr);
1039
- }
1040
-
1041
- if (['not'].includes(operator)) {
1042
- // A 'not' expression is an object with only one inner field and inner operator
1043
- Object.keys(value).map((notKey, notIdx) => {
1044
- const innerOperator = notKey;
1045
- const innerValue = value[notKey];
1046
- const innerField = value.field; // Map the expression when we've looped and scoped to
1047
- // the second property inside the clause
1048
-
1049
- if (notIdx === 1) {
1050
- expression = contensisCoreApi.Op.not(contensisCoreApi.Op[innerOperator](innerField, innerValue));
1051
- }
1052
- });
1053
- }
1054
- } // Map the expression when we've looped and scoped to
1055
- // the second property inside the clause
1056
-
1057
-
1058
- operator = Object.keys(clause).find(clauseKey => !['field', 'weight'].includes(clauseKey));
1059
-
1060
- if (idx === 1 && // operator !== 'and' &&
1061
- // operator !== 'or' &&
1062
- operator !== 'between' && operator !== 'distanceWithin') {
1063
- expression = operator === 'freeText' || operator === 'contains' ? contensisCoreApi.Op[operator](field, value) : operator === 'in' ? contensisCoreApi.Op[operator](field, ...value) : contensisCoreApi.Op[operator](field, value);
1064
- if (typeof weight === 'number') expression = expression.weight(weight);
1065
- }
1066
- });
1067
- return expression;
1068
- });
1069
- };
1070
- const termExpressions = (searchTerm, weightedSearchFields) => {
1071
- if (searchTerm && weightedSearchFields && weightedSearchFields.length > 0) {
1072
- // Extract any phrases in quotes to array
1073
- const quotedPhrases = extractQuotedPhrases(searchTerm); // Modify the search term to remove any quoted phrases to leave any remaining terms
1074
-
1075
- let modifiedSearchTerm = searchTerm;
1076
- quotedPhrases.forEach(qp => modifiedSearchTerm = modifiedSearchTerm.replace(qp, '').replace('""', '').trim()); // Push to the operators array to include in the query
1077
-
1078
- const operators = []; // Helper functions to generate Op expressions
1079
-
1080
- const containsOp = (f, term) => fieldExpression(f.fieldId, fixFreeTextForElastic(term), 'contains', f.weight);
1081
-
1082
- const freeTextOp = (f, term) => fieldExpression(f.fieldId, fixFreeTextForElastic(term), 'freeText', f.weight); // For each weighted search field
1083
-
1084
-
1085
- weightedSearchFields.forEach(wsf => {
1086
- // Push to field operators
1087
- const fieldOperators = []; // Add operator expressions for modified search term
1088
-
1089
- if (modifiedSearchTerm) {
1090
- if ([Fields.keywords, Fields.sys.filename, Fields.sys.uri].includes(wsf.fieldId)) {
1091
- fieldOperators.push(...containsOp(wsf, modifiedSearchTerm));
1092
- } else {
1093
- if ([Fields.entryTitle].includes(wsf.fieldId)) {
1094
- fieldOperators.push(contensisCoreApi.Op.or(...containsOp(wsf, modifiedSearchTerm), ...freeTextOp(wsf, modifiedSearchTerm)));
1095
- } else {
1096
- fieldOperators.push(...freeTextOp(wsf, modifiedSearchTerm));
1097
- }
1098
- }
1099
- } // Add operator expressions for any quoted phrases
1100
-
1101
-
1102
- quotedPhrases.forEach(qp => fieldOperators.push(...containsOp(wsf, qp))); // If we are using multiple operators for a field we will
1103
- // wrap each field inside an And operator so we will match
1104
- // all terms/phrases rather than any terms/phrases
1105
-
1106
- if (fieldOperators.length > 1) {
1107
- operators.push(contensisCoreApi.Op.and(...fieldOperators));
1108
- } else {
1109
- operators.push(...fieldOperators);
1110
- }
1111
- }); // Wrap operators in an Or operator
1112
-
1113
- return [contensisCoreApi.Op.or().addRange(operators).add(contensisCoreApi.Op.freeText(Fields.searchContent, searchTerm))];
1114
- } else if (searchTerm) {
1115
- // Searching without weightedSearchFields defined will fall back
1116
- // to a default set of search fields with arbritary weights set.
1117
- return [contensisCoreApi.Op.or(contensisCoreApi.Op.equalTo(Fields.entryTitle, searchTerm).weight(10), contensisCoreApi.Op.freeText(Fields.entryTitle, searchTerm).weight(2), contensisCoreApi.Op.freeText(Fields.entryDescription, searchTerm).weight(2), contensisCoreApi.Op.contains(Fields.keywords, searchTerm).weight(2), contensisCoreApi.Op.contains(Fields.sys.uri, searchTerm).weight(2), contensisCoreApi.Op.contains(Fields.sys.allUris, searchTerm), contensisCoreApi.Op.freeText(Fields.searchContent, searchTerm))];
1118
- } else {
1119
- return [];
1120
- }
1121
- };
1122
-
1123
- const filterQuery = (contentTypeIds, versionStatus, customWhere) => {
1124
- const query = new contensisCoreApi.Query(...[...contentTypeIdExpression(contentTypeIds), ...defaultExpressions(versionStatus), ...customWhereExpressions(customWhere)]);
1125
- query.orderBy = contensisCoreApi.OrderBy.asc(Fields.entryTitle);
1126
- query.pageSize = 100;
1127
- return query;
1128
- };
1129
- const searchQuery = ({
1130
- assetTypes,
1131
- contentTypeIds,
1132
- customWhere,
1133
- dynamicOrderBy,
1134
- excludeIds,
1135
- featuredResults,
1136
- fields,
1137
- filters,
1138
- includeInSearchFields,
1139
- languages,
1140
- pageSize,
1141
- pageIndex,
1142
- orderBy,
1143
- searchTerm,
1144
- versionStatus,
1145
- webpageTemplates,
1146
- weightedSearchFields
1147
- }, isFeatured = false) => {
1148
- let expressions = [...termExpressions(searchTerm, weightedSearchFields), ...defaultExpressions(versionStatus), ...includeInSearchExpressions(webpageTemplates, includeInSearchFields), ...languagesExpression(languages), ...customWhereExpressions(customWhere), ...excludeIdsExpression(excludeIds)];
1149
- if (isFeatured) expressions = [...expressions, ...featuredResultsExpression(featuredResults)];
1150
- if (!isFeatured || featuredResults && !featuredResults.contentTypeId) expressions = [...expressions, ...filterExpressions(filters), ...contentTypeIdExpression(contentTypeIds, webpageTemplates, assetTypes)];
1151
- const query = new contensisCoreApi.Query(...expressions);
1152
- if (!searchTerm) query.orderBy = orderByExpression(orderBy);
1153
- if (dynamicOrderBy && dynamicOrderBy.length) query.orderBy = orderByExpression(dynamicOrderBy);
1154
-
1155
- if (fields && fields.length > 0 && !isFeatured) {
1156
- query.fields = fields;
1157
- }
1158
-
1159
- query.pageIndex = isFeatured ? 0 : pageIndex;
1160
- query.pageSize = isFeatured && typeof featuredResults.count === 'number' ? featuredResults.count : pageSize;
1161
- return query;
1162
- };
1163
-
1164
- var queries = /*#__PURE__*/Object.freeze({
1165
- __proto__: null,
1166
- filterQuery: filterQuery,
1167
- searchQuery: searchQuery
1168
- });
1169
-
1170
- const searchUriTemplate = {
1171
- path: ({
1172
- state,
1173
- facet,
1174
- pageIndex
1175
- }) => {
1176
- const currentFacet = getSearchContext(state) !== Context$1.listings && (facet || getCurrentFacet(state));
1177
- const currentPath = selectCurrentPath(state) || '/search';
1178
- const newPath = currentFacet ? `${currentPath}/${currentFacet}` : currentPath;
1179
- if (pageIndex) return `${newPath}/${pageIndex + 1}`;
1180
- return newPath;
1181
- },
1182
- search: ({
1183
- state,
1184
- facet,
1185
- orderBy,
1186
- term
1187
- }) => {
1188
- const searchContext = getSearchContext(state); // Lose stateFilters and currentSearch if a new
1189
- // term is passed via an argument
1190
-
1191
- const stateFilters = term ? {} : Object.fromEntries(Object.entries(getSelectedFilters(state, facet, searchContext, 'js')).map(([key, f]) => [key, f === null || f === void 0 ? void 0 : f.join(',')]));
1192
- const currentSearch = !term && getImmutableOrJS(state, ['routing', 'location', 'search']);
1193
- const currentQs = removeEmptyAttributes(queryString__default["default"].parse(currentSearch));
1194
- if (orderBy) currentQs.orderBy = orderBy;
1195
- const searchTerm = getSearchTerm(state); // Use Immutable's merge to merge the stateFilters with any current Qs
1196
- // to build the new Qs.
1197
-
1198
- const mergedSearch = removeEmptyAttributes({ ...merge__default["default"](currentQs, stateFilters),
1199
- term: searchTerm
1200
- });
1201
- return queryString__default["default"].stringify(mergedSearch);
1202
- },
1203
- hash: {
1204
- $path: 'state',
1205
- $formatting: state => getImmutableOrJS(state, ['routing', 'location', 'hash'], '').replace('#', '')
1206
- }
1207
- };
1208
-
1209
- const mapStateToSearchUri = params => mapJson__default["default"](params, searchUriTemplate);
1210
-
1211
- const mapEntriesToSearchResults = ({
1212
- mappers,
1213
- mapper,
1214
- context,
1215
- facet
1216
- }, items, state) => {
1217
- const mapperFunc = mapper || mappers && mappers.results;
1218
- return items && typeof mapperFunc === 'function' ? mapperFunc(items, facet, context, state) : [];
1219
- };
1220
-
1221
- const facetTemplate = {
1222
- type: () => SET_SEARCH_ENTRIES,
1223
- context: 'action.context',
1224
- facet: 'action.facet',
1225
- mappers: 'action.mappers',
1226
- nextFacet: {
1227
- entries: {
1228
- isLoading: () => false,
1229
- isError: () => false
1230
- },
1231
- featuredEntries: {
1232
- isLoading: () => false,
1233
- isError: () => false
1234
- },
1235
- featuredResults: ({
1236
- action,
1237
- featuredResult,
1238
- state
1239
- }) => mapEntriesToSearchResults(action, getItemsFromResult(featuredResult), state),
1240
- queryDuration: 'result.duration',
1241
- pagingInfo: {
1242
- isLoading: () => false,
1243
- pageCount: {
1244
- $path: 'result.payload.pageCount',
1245
- $default: 0
1246
- },
1247
- totalCount: {
1248
- $path: 'result.payload.totalCount',
1249
- $default: 0
1250
- },
1251
- pageSize: {
1252
- $path: 'result.payload.pageSize',
1253
- $default: 0
1254
- },
1255
- pageIndex: 'pageIndex',
1256
- pagesLoaded: {
1257
- $path: 'action.queryParams',
1258
- $formatting: ({
1259
- pageIndex,
1260
- pagesLoaded
1261
- }) => {
1262
- const loaded = [...(pagesLoaded || [])];
1263
-
1264
- if (isNaN(loaded.find(l => l === pageIndex))) {
1265
- loaded.push(pageIndex);
1266
- }
1267
-
1268
- return loaded.sort((a, b) => a - b);
1269
- }
1270
- },
1271
- prevPageIndex: 'action.queryParams.prevPageIndex'
1272
- },
1273
- preloaded: {
1274
- $path: 'preload',
1275
- $default: false
1276
- },
1277
- results: ({
1278
- action,
1279
- pageIndex,
1280
- result,
1281
- prevResults,
1282
- state
1283
- }) => {
1284
- const {
1285
- loadMorePaging,
1286
- pagesLoaded,
1287
- prevPageIndex
1288
- } = action.queryParams;
1289
- const results = mapEntriesToSearchResults(action, getItemsFromResult(result), state);
1290
- if (!loadMorePaging) return results; // add a _pageIndex property to the returned results to help us later
1291
-
1292
- const nextResults = results.map((r, idx) => ({
1293
- _pageIndex: pageIndex,
1294
- _pagePosition: idx,
1295
- ...r
1296
- }));
1297
- const loadedPages = pagesLoaded || []; // if pageIndex is found in loadedPages, we have already loaded this page
1298
-
1299
- if (!isNaN(loadedPages.find(l => l === pageIndex))) return prevResults; // Determine where we put the results depending on if we
1300
- // are paging forwards, backwards, or doing a new search
1301
-
1302
- const firstResultSet = pageIndex > prevPageIndex ? prevResults || [] : nextResults;
1303
- const secondResultSet = pageIndex > prevPageIndex ? nextResults : prevResults || [];
1304
- const onlyResultSet = loadedPages.length === 0 ? nextResults : false;
1305
- return onlyResultSet || [...firstResultSet, ...secondResultSet];
1306
- }
1307
- },
1308
- preload: 'action.preload',
1309
- ogState: 'action.ogState',
1310
- debug: 'action.debug'
1311
- };
1312
- const filterTemplate = {
1313
- type: ({
1314
- type
1315
- }) => type || LOAD_FILTERS_COMPLETE,
1316
- context: 'context',
1317
- facetKey: 'facetKey',
1318
- filterKey: 'filterKey',
1319
- nextFilter: {
1320
- isLoading: () => false,
1321
- isError: ({
1322
- type
1323
- }) => type === LOAD_FILTERS_ERROR,
1324
- items: ({
1325
- payload,
1326
- selectedKeys,
1327
- mapper
1328
- }) => {
1329
- if (payload && (payload.items || payload.children)) {
1330
- const items = (payload.items || payload.children).map(item => {
1331
- var _item$sys;
1332
-
1333
- item.isSelected = selectedKeys === null || selectedKeys === void 0 ? void 0 : selectedKeys.includes((item === null || item === void 0 ? void 0 : (_item$sys = item.sys) === null || _item$sys === void 0 ? void 0 : _item$sys.id) || item.key);
1334
- return item;
1335
- });
1336
- return mapper(items);
1337
- }
1338
-
1339
- return [];
1340
- }
1341
- },
1342
- error: {
1343
- $path: 'error',
1344
- $disable: e => !e
1345
- }
1346
- };
1347
-
1348
- const filterExpressionMapper = {
1349
- // Expression type: so we can identify how to build the query
1350
- expressionType: ({
1351
- filter
1352
- }) => filter.contentTypeId ? FilterExpressionTypes.contentType : FilterExpressionTypes.field,
1353
- // Key: so we can target the query to a specific field
1354
- key: 'filter.fieldId',
1355
- // Value: so we can filter a specific field by an array of values
1356
- // e.g. taxonomy key or contentTypeId array
1357
- value: 'selectedValue',
1358
- operator: 'filter.fieldOperator'
1359
- };
1360
-
1361
- const mapFilterToFilterExpression = filter => mapJson__default["default"](filter, filterExpressionMapper);
1362
-
1363
- const mapFiltersToFilterExpression = (filters, selectedFilters) => {
1364
- if (!selectedFilters || Object.keys(selectedFilters).length === 0) return [];
1365
- const filterExpressions = []; // Iterate through the keys in selectedFilters and locate
1366
- // the items that are selected and queryable
1367
-
1368
- Object.entries(selectedFilters).map(([fkey, selectedValue]) => {
1369
- const filter = filters[fkey];
1370
-
1371
- if (selectedValue && filter) {
1372
- const selectedItems = filter.items && filter.items.filter(itm => itm.isSelected) || []; // Where we have a value for a selectedFilter
1373
- // and a filter is found for the current key
1374
- // map the filter to a filterExpression object
1375
-
1376
- const expr = mapFilterToFilterExpression({
1377
- filter,
1378
- selectedItems,
1379
- selectedValue
1380
- });
1381
- filterExpressions.push(expr);
1382
- }
1383
- });
1384
- return filterExpressions;
1385
- };
1386
-
1387
- const queryParamsTemplate = {
1388
- assetTypes: root => getQueryParameter(root, 'assetTypes', []),
1389
- contentTypeIds: root => getQueryParameter(root, 'contentTypeIds', []),
1390
- customWhere: root => getQueryParameter(root, 'customWhere', []),
1391
- dynamicOrderBy: root => getQueryParameter(root, 'dynamicOrderBy', []),
1392
- env: ({
1393
- state,
1394
- facet,
1395
- context
1396
- }) => getCustomEnv(state, facet, context),
1397
- excludeIds: ({
1398
- action: {
1399
- excludeIds
1400
- }
1401
- }) => {
1402
- // Exclude current route entry id from minilist searches or any supplied ids
1403
- if (excludeIds) return Array.isArray(excludeIds) ? excludeIds : excludeIds.split(',').map(id => id.trim());
1404
- return null;
1405
- },
1406
- featuredResults: root => getQueryParameter(root, 'featuredResults', null),
1407
- fields: root => getQueryParameter(root, 'fields', []),
1408
- filters: ({
1409
- state,
1410
- facet,
1411
- context
1412
- }) => {
1413
- const stateFilters = getFilters(state, facet, context, 'js');
1414
- const selectedFilters = getSelectedFilters(state, facet, context, 'js'); // Use another mapping function to map the filter parameters for the query
1415
-
1416
- const filterParams = mapFiltersToFilterExpression(stateFilters, selectedFilters);
1417
- return filterParams;
1418
- },
1419
- includeInSearchFields: root => getQueryParameter(root, 'includeInSearch', []),
1420
- internalPageIndex: ({
1421
- action,
1422
- state
1423
- }) => getPageIndex(state, '', action.context),
1424
- internalPaging: root => getQueryParameter(root, 'internalPaging', false),
1425
- languages: ({
1426
- action
1427
- }) => action.defaultLang ? [action.defaultLang] : [],
1428
- linkDepth: root => getQueryParameter(root, 'linkDepth', 0),
1429
- loadMorePaging: root => getQueryParameter(root, 'loadMorePaging', false),
1430
- orderBy: root => getQueryParameter(root, 'orderBy', []),
1431
- pageIndex: root => {
1432
- const {
1433
- action,
1434
- state
1435
- } = root;
1436
- if (getQueryParameter(root, 'internalPaging', false)) return 0;
1437
- if (action.type === UPDATE_PAGE_INDEX) return action.params.pageIndex;
1438
- return !action.preload ? getPageIndex(state, '', action.context) : 0;
1439
- },
1440
- pageSize: root => getQueryParameter(root, 'pageSize'),
1441
- pagesLoaded: ({
1442
- state,
1443
- facet,
1444
- context
1445
- }) => getPagesLoaded(state, facet, context),
1446
- prevPageIndex: ({
1447
- state,
1448
- facet,
1449
- context
1450
- }) => getPrevPageIndex(state, facet, context),
1451
- projectId: ({
1452
- state,
1453
- facet,
1454
- context
1455
- }) => {
1456
- var _getFacet;
1457
-
1458
- return (_getFacet = getFacet(state, facet, context)) === null || _getFacet === void 0 ? void 0 : _getFacet.projectId;
1459
- },
1460
- searchTerm: root => root.context !== Context$1.minilist || getQueryParameter(root, 'useSearchTerm', false) ? getSearchTerm(root.state) : '',
1461
- selectedFilters: ({
1462
- state,
1463
- facet,
1464
- context
1465
- }) => Object.fromEntries(Object.entries(getSelectedFilters(state, facet, context, 'js')).map(([key, f]) => [key, f === null || f === void 0 ? void 0 : f.join(',')])),
1466
- versionStatus: ({
143
+ const {
144
+ getCurrent: getCurrent$1,
145
+ getCurrentTab,
146
+ getFacet,
147
+ getFacetsTotalCount,
148
+ getFacetTitles,
149
+ getFeaturedResults: getFeaturedResults$1,
150
+ getIsLoading: getIsLoading$1,
151
+ getPageIndex: getPageIndex$1,
152
+ getPageIsLoading: getPageIsLoading$1,
153
+ getQueryParameter: getQueryParameter$1,
154
+ getRenderableFilters: getRenderableFilters$1,
155
+ getSearchTerm: getSearchTerm$1,
156
+ getSearchTotalCount,
157
+ getTabFacets,
158
+ getTabsAndFacets,
159
+ getTotalCount
160
+ } = sagas.selectFacets;
161
+
162
+ const makeSelectFacetsProps = () => reselect.createSelector(state => state, (_, mappers) => mappers, (state, mappers) => ({
163
+ currentFacet: getCurrent$1(state),
164
+ currentPageIndex: getPageIndex$1(state),
165
+ currentTabIndex: getCurrentTab(state),
166
+ facet: getFacet(state),
167
+ facetTitles: getFacetTitles(state),
168
+ facets: getTabFacets(state),
169
+ facetsTotalCount: getFacetsTotalCount(state),
170
+ featured: getFeaturedResults$1(state),
171
+ filters: getRenderableFilters$1(state),
172
+ isLoading: getIsLoading$1(state),
173
+ pageIsLoading: getPageIsLoading$1(state),
174
+ paging: sagas.getPaging(state, '', sagas.Context.facets, 'js'),
175
+ results: sagas.getResults(state, '', sagas.Context.facets, 'js'),
176
+ resultsInfo: mappers && typeof mappers.resultsInfo === 'function' && mappers.resultsInfo(state),
177
+ searchTerm: getSearchTerm$1(state),
178
+ searchTotalCount: getSearchTotalCount(state),
179
+ selectedFilters: sagas.getSelectedFilters(state, '', sagas.Context.facets, 'js'),
180
+ sortOrder: getQueryParameter$1({
1467
181
  state
1468
- }) => selectVersionStatus(state),
1469
- weightedSearchFields: root => {
1470
- const wsf = getQueryParameter(root, 'weightedSearchFields', []);
1471
- const deduped = wsf.filter((v, i, a) => a.findIndex(t => t.fieldId === v.fieldId) === i);
1472
- return deduped; // return wsf;
1473
- },
1474
- webpageTemplates: root => getQueryParameter(root, 'webpageTemplates', [])
1475
- };
1476
-
1477
- const mapStateToQueryParams = sourceJson => mapJson__default["default"](sourceJson, queryParamsTemplate);
182
+ }, 'dynamicOrderBy', []),
183
+ tabsAndFacets: getTabsAndFacets(state),
184
+ totalCount: getTotalCount(state)
185
+ }));
1478
186
 
1479
- /**
1480
- * 1, Generates all the parameters required to run the search query.
1481
- * 2, Tells us if we should run the search.
1482
- * @param {object} action
1483
- * @param {AppState} state
1484
- * @returns [queryParams, runSearch]
1485
- */
1486
- const generateQueryParams = (action, state) => {
187
+ const useFacets = ({
188
+ mappers
189
+ } = {
190
+ id: ''
191
+ }) => {
192
+ const dispatch = reactRedux.useDispatch();
193
+ const m = mappers || defaultMappers;
194
+ const selectListingProps = React.useMemo(makeSelectFacetsProps, [m]);
195
+ const dispatchProps = {
196
+ clearFilters: () => dispatch(sagas.withMappers(sagas.clearFilters(), m)),
197
+ updateCurrentFacet: facet => dispatch(sagas.withMappers(sagas.updateCurrentFacet(facet), m)),
198
+ updateCurrentTab: id => sagas.withMappers(sagas.updateCurrentTab(id), m),
199
+ updatePageIndex: pageIndex => dispatch(sagas.withMappers(sagas.updatePageIndex(pageIndex), m)),
200
+ updateSearchTerm: term => dispatch(sagas.withMappers(sagas.updateSearchTerm(term), m)),
201
+ updateSelectedFilters: (filter, key, isUnknownItem = false) => dispatch(sagas.withMappers(sagas.updateSelectedFilters(filter, key, isUnknownItem), m)),
202
+ updateSortOrder: orderBy => dispatch(sagas.withMappers(sagas.updateSortOrder(orderBy), m))
203
+ };
1487
204
  const {
1488
- context,
1489
- facet
1490
- } = action; // Map parameters using state and some additional
1491
- // inputs from the action
1492
-
1493
- const queryParams = mapStateToQueryParams({
1494
- context,
205
+ currentFacet,
206
+ currentPageIndex,
207
+ currentTabIndex,
1495
208
  facet,
1496
- action,
1497
- state
1498
- });
1499
- return [queryParams, runSearch(action, state, queryParams)];
1500
- };
1501
- /**
1502
- * Checks if we have already loaded everything we're asking for and tells us to run the search or not
1503
- * @param action
1504
- * @param state
1505
- */
1506
-
1507
- const runSearch = (action, state, queryParams) => {
1508
- const {
1509
- context,
1510
- defaultLang,
209
+ facets,
210
+ facetsTotalCount,
211
+ facetTitles,
212
+ featured,
213
+ filters,
214
+ isLoading,
215
+ paging,
216
+ pageIsLoading,
217
+ results,
218
+ resultsInfo,
219
+ searchTerm,
220
+ searchTotalCount,
221
+ selectedFilters,
222
+ sortOrder,
223
+ tabsAndFacets,
224
+ totalCount
225
+ } = reactRedux.useSelector(state => selectListingProps(state, m));
226
+ return {
227
+ currentFacet,
228
+ currentPageIndex,
229
+ currentTabIndex,
1511
230
  facet,
1512
- ogState = state,
1513
- preload,
1514
- ssr
1515
- } = action;
1516
- let willRun = false;
1517
- const facetIsLoaded = defaultLang ? false : getIsLoaded(state, context, facet);
1518
- const stateParams = { ...getQueryParams(ogState, facet, context)
231
+ facets,
232
+ facetsTotalCount,
233
+ facetTitles,
234
+ featured,
235
+ filters,
236
+ isLoading,
237
+ paging,
238
+ pageIsLoading,
239
+ results,
240
+ resultsInfo,
241
+ searchTerm,
242
+ searchTotalCount,
243
+ selectedFilters,
244
+ sortOrder,
245
+ tabsAndFacets,
246
+ totalCount,
247
+ ...dispatchProps
1519
248
  };
1520
- stateParams.pageIndex = getPageIndex(ogState, facet, context);
1521
- stateParams.searchTerm = getSearchTerm(ogState);
1522
-
1523
- if (context === Context$1.facets && ssr || // context === Context.minilist ||
1524
- preload || !facetIsLoaded || filterParamsChanged(action) || defaultLang) {
1525
- willRun = true;
1526
- } else {
1527
- // Don't execute the search if the inbound query params
1528
- // are the same as what we already have in state
1529
- Object.entries(stateParams).forEach(([param, value]) => {
1530
- const queryParam = queryParams[param];
1531
-
1532
- if (JSON.stringify(value) !== JSON.stringify(queryParam)) {
1533
- willRun = true;
1534
- }
1535
- });
1536
- }
1537
-
1538
- const internalPaging = getIsInternalPaging(ogState, facet, context);
1539
-
1540
- if (internalPaging && facetIsLoaded) {
1541
- willRun = false;
1542
- }
1543
-
1544
- return willRun;
1545
- };
1546
- /**
1547
- * This will tell us if filter parameters have been
1548
- * changed by some external event such as a route change
1549
- * @param action
1550
- * @returns true or false
1551
- */
1552
-
1553
- const filterParamsChanged = (action, state) => {
1554
- const {
1555
- context,
1556
- facet,
1557
- params,
1558
- ogState = state
1559
- } = action;
1560
- const selectedFilters = getSelectedFilters(ogState, facet, context, 'js');
1561
- const paramsChanged = Object.entries(selectedFilters).map(([filterKey, selectedValues]) => {
1562
- const inboundValues = params && params[filterKey] && params[filterKey].split(',') || [];
1563
- if (!areArraysEqualSets(selectedValues, inboundValues)) return true;
1564
- });
1565
- return paramsChanged.filter(f => f === true).length > 0;
1566
- };
1567
- /* eslint-disable no-console */
1568
-
1569
- const debugExecuteSearch = (action, state) => {
1570
- const [queryParams, runSearch] = generateQueryParams(action, state);
1571
- console.log('runSearch', runSearch, 'action', action, 'filterParamsChanged', filterParamsChanged(action, state), 'getIsLoaded(state, context, facet)', getIsLoaded(state, action.context, action.facet));
1572
- const stateParams = getQueryParams(action.ogState || state, action.facet, action.context);
1573
- stateParams.pageIndex = getPageIndex(action.ogState || state, action.facet, action.context);
1574
- stateParams.searchTerm = getSearchTerm(action.ogState || state);
1575
- console.log(stateParams, queryParams);
1576
- console.log('getSelectedFilters', getSelectedFilters(action.ogState || state, action.facet, action.context, 'js'), 'params', action.params);
1577
- };
1578
-
1579
- // Base mapping, fields that are the same across all mappings
1580
- // to save repeating these elements in every mapper, spread this
1581
- // into your discrete mappings
1582
-
1583
- const base = {
1584
- contentTypeId: Fields.sys.contentTypeId,
1585
- title: 'entryTitle',
1586
- key: 'sys.id',
1587
- path: 'sys.slug',
1588
- isSelected: 'isSelected'
1589
- };
1590
-
1591
- const mapEntriesToFilterItems = entries => {
1592
- if (!entries) return [];
1593
- return entries.map(entry => {
1594
- const template = base;
1595
-
1596
- if (template) {
1597
- return mapJson__default["default"](entry, template);
1598
- }
1599
-
1600
- return entry;
1601
- });
1602
249
  };
1603
250
 
1604
- const searchSagas = [effects.takeEvery(CLEAR_FILTERS, clearFilters), effects.takeEvery(DO_SEARCH, doSearch), effects.takeEvery(SET_ROUTE_FILTERS, loadFilters), effects.takeEvery(SET_SEARCH_ENTRIES, preloadOtherFacets), effects.takeEvery(UPDATE_CURRENT_FACET, updateCurrentFacet), effects.takeEvery(UPDATE_CURRENT_TAB, updateCurrentTab), effects.takeEvery(UPDATE_PAGE_INDEX, updatePageIndex), effects.takeEvery(UPDATE_SEARCH_TERM, updateSearchTerm), effects.takeEvery(UPDATE_SORT_ORDER, updateSortOrder), effects.takeEvery(UPDATE_SELECTED_FILTERS, applySearchFilter)];
1605
-
1606
- const toJS = obj => obj && 'toJS' in obj && typeof obj.toJS === 'function' ? obj.toJS() : obj;
1607
-
1608
- function* setRouteFilters(action) {
1609
- const {
1610
- mappers,
1611
- params,
1612
- listingType,
1613
- defaultLang,
1614
- debug
1615
- } = action;
1616
- const context = listingType ? Context$1.listings : Context$1.facets;
1617
- const state = toJS(yield effects.select());
1618
- const ssr = getIsSsr(state); // Get current facet from params or state
1619
-
1620
- let currentFacet = params && params.facet || listingType; // Pick the default facet from initialState
1621
-
1622
- if (!currentFacet) {
1623
- var _Object$keys;
1624
-
1625
- const tabs = getSearchTabs(state, 'js');
1626
- 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]) || '';
1627
- }
1628
-
1629
- const nextAction = {
1630
- type: SET_ROUTE_FILTERS,
1631
- context,
1632
- facet: currentFacet,
1633
- mappers,
1634
- params,
1635
- defaultLang,
1636
- ssr,
1637
- debug
1638
- };
1639
- yield effects.put(nextAction); // Using call instead of triggering from the put
1640
- // to allow this exported saga to continue during SSR
1641
-
1642
- yield effects.call(ensureSearch, { ...nextAction,
1643
- ogState: state
1644
- });
1645
- }
1646
- function* doSearch(action) {
1647
- const state = toJS(yield effects.select());
1648
-
1649
- if (action.config) {
1650
- // If the action contains a config object, we can add this to the
1651
- // state at runtime
1652
- yield effects.put({ ...action,
1653
- type: APPLY_CONFIG
1654
- });
1655
- }
251
+ const {
252
+ getCurrent,
253
+ getFeaturedResults,
254
+ getIsLoading,
255
+ getListing,
256
+ getPageIndex,
257
+ getPageIsLoading,
258
+ getQueryParameter,
259
+ getRenderableFilters,
260
+ getSearchTerm
261
+ } = sagas.selectListing;
262
+
263
+ const makeSelectListingProps = () => reselect.createSelector(state => state, (_, mappers) => mappers, (state, mappers) => ({
264
+ currentListing: getCurrent(state),
265
+ currentPageIndex: getPageIndex(state),
266
+ listing: getListing(state),
267
+ featured: getFeaturedResults(state),
268
+ filters: getRenderableFilters(state),
269
+ isLoading: getIsLoading(state),
270
+ pageIsLoading: getPageIsLoading(state),
271
+ paging: sagas.getPaging(state, '', sagas.Context.listings, 'js'),
272
+ results: sagas.getResults(state, '', sagas.Context.listings, 'js'),
273
+ resultsInfo: mappers && typeof mappers.resultsInfo === 'function' && mappers.resultsInfo(state),
274
+ searchTerm: getSearchTerm(state),
275
+ selectedFilters: sagas.getSelectedFilters(state, '', sagas.Context.listings, 'js'),
276
+ sortOrder: getQueryParameter({
277
+ state
278
+ }, 'dynamicOrderBy', [])
279
+ }));
1656
280
 
1657
- const nextAction = { ...action,
1658
- type: SET_SEARCH_FILTERS,
1659
- ssr: getIsSsr(state)
281
+ const useListing = ({
282
+ mappers
283
+ } = {
284
+ id: ''
285
+ }) => {
286
+ const dispatch = reactRedux.useDispatch();
287
+ const m = mappers || defaultMappers;
288
+ const selectListingProps = React.useMemo(makeSelectListingProps, [m]);
289
+ const dispatchProps = {
290
+ clearFilters: () => dispatch(sagas.withMappers(sagas.clearFilters(), m)),
291
+ updateCurrentFacet: facet => dispatch(sagas.withMappers(sagas.updateCurrentFacet(facet), m)),
292
+ updatePageIndex: pageIndex => dispatch(sagas.withMappers(sagas.updatePageIndex(pageIndex), m)),
293
+ updateSearchTerm: term => dispatch(sagas.withMappers(sagas.updateSearchTerm(term), m)),
294
+ updateSelectedFilters: (filter, key, isUnknownItem = false) => dispatch(sagas.withMappers(sagas.updateSelectedFilters(filter, key, isUnknownItem), m)),
295
+ updateSortOrder: orderBy => dispatch(sagas.withMappers(sagas.updateSortOrder(orderBy), m))
1660
296
  };
1661
- yield effects.put(nextAction);
1662
- yield effects.call(ensureSearch, { ...nextAction,
1663
- ogState: state
1664
- });
1665
- }
1666
-
1667
- function* loadFilters(action) {
1668
297
  const {
1669
- facet: facetKey,
1670
- context,
1671
- mappers = {}
1672
- } = action;
1673
- const filtersToLoad = yield effects.select(getFiltersToLoad, facetKey, context, 'js');
1674
-
1675
- if (filtersToLoad.length > 0) {
1676
- yield effects.put({
1677
- type: LOAD_FILTERS,
1678
- filtersToLoad,
1679
- facetKey,
1680
- context
1681
- });
1682
- const selectedKeys = yield effects.select(getSelectedFilters, facetKey, context, 'js');
1683
- const facet = yield effects.select(getFacet, facetKey, context, 'js');
1684
- const filters = facet.filters || {};
1685
- const projectId = facet.projectId;
1686
- const filtersToLoadSagas = filters && filtersToLoad.map((filterKey = '') => {
1687
- return effects.call(loadFilter, {
1688
- facetKey,
1689
- filterKey,
1690
- filter: filters[filterKey],
1691
- projectId,
1692
- selectedKeys: selectedKeys[filterKey],
1693
- context,
1694
- mapper: 'filterItems' in mappers && mappers.filterItems || mapEntriesToFilterItems
1695
- });
1696
- });
1697
- if (filtersToLoadSagas) yield effects.all(filtersToLoadSagas);
1698
- }
1699
- }
1700
-
1701
- function* loadFilter(action) {
1702
- const {
1703
- facetKey,
1704
- filterKey,
1705
- filter,
1706
- projectId,
1707
- selectedKeys,
1708
- context,
1709
- mapper
1710
- } = action;
1711
- const {
1712
- contentTypeId,
1713
- customWhere,
1714
- path
1715
- } = filter;
1716
- const createStateFrom = {
1717
- type: LOAD_FILTERS_COMPLETE,
1718
- context,
1719
- error: undefined,
1720
- facetKey,
1721
- filterKey,
1722
- payload: {},
1723
- selectedKeys,
1724
- mapper
298
+ currentListing,
299
+ currentPageIndex,
300
+ featured,
301
+ filters,
302
+ isLoading,
303
+ listing,
304
+ paging,
305
+ pageIsLoading,
306
+ results,
307
+ resultsInfo,
308
+ searchTerm,
309
+ selectedFilters,
310
+ sortOrder
311
+ } = reactRedux.useSelector(state => selectListingProps(state, m));
312
+ return {
313
+ currentListing,
314
+ currentPageIndex,
315
+ featured,
316
+ filters,
317
+ isLoading,
318
+ listing,
319
+ pageIsLoading,
320
+ paging,
321
+ results,
322
+ resultsInfo,
323
+ searchTerm,
324
+ selectedFilters,
325
+ sortOrder,
326
+ title: listing.title,
327
+ ...dispatchProps
1725
328
  };
1726
-
1727
- try {
1728
- if (contentTypeId) {
1729
- const versionStatus = yield effects.select(selectVersionStatus);
1730
- const query = filterQuery(Array.isArray(contentTypeId) ? contentTypeId : [contentTypeId], versionStatus, customWhere);
1731
- const payload = yield cachedSearch.search(query, 0, projectId);
1732
- if (!payload) throw new Error('No payload returned by search');
1733
- if (payload.type === 'error') throw payload;
1734
- createStateFrom.payload = payload;
1735
- }
1736
-
1737
- if (path) {
1738
- const payload = yield cachedSearch.getTaxonomyNodeByPath(path, projectId);
1739
- if (!payload) throw new Error(`No payload returned for taxonomy path: '${path}'`);
1740
- if (payload.type === 'error') throw payload;
1741
- createStateFrom.payload = payload;
1742
- }
1743
- } catch (error) {
1744
- createStateFrom.type = LOAD_FILTERS_ERROR;
1745
- createStateFrom.error = error;
1746
- }
1747
-
1748
- const nextAction = mapJson__default["default"](createStateFrom, filterTemplate);
1749
- yield effects.put(nextAction);
1750
- }
1751
-
1752
- function* ensureSearch(action) {
1753
- const {
1754
- context,
1755
- facet,
1756
- debug
1757
- } = action;
1758
-
1759
- try {
1760
- const state = yield effects.select();
1761
- const nextAction = { ...action,
1762
- ogState: action.ogState || state
1763
- };
1764
- const [queryParams, runSearch] = generateQueryParams(nextAction, state);
1765
- if (debug && (debug === true || debug.executeSearch)) debugExecuteSearch(nextAction, state);
1766
-
1767
- if (runSearch) {
1768
- yield effects.put({
1769
- type: EXECUTE_SEARCH,
1770
- facet,
1771
- context
1772
- });
1773
- yield effects.call(executeSearch, { ...nextAction,
1774
- context,
1775
- facet,
1776
- queryParams,
1777
- debug
1778
- });
1779
- }
1780
- } catch (error) {
1781
- // eslint-disable-next-line import/namespace
1782
- log__namespace.error(...['Error running search saga:', error, error.stack]);
1783
- }
1784
- }
1785
-
1786
- function* executeSearch(action) {
1787
- const {
1788
- context,
1789
- facet,
1790
- queryParams,
1791
- mappers
1792
- } = action;
1793
-
1794
- try {
1795
- const state = yield effects.select();
1796
- let result = {};
1797
- let featuredResult;
1798
- let featuredQuery;
1799
- const customApi = getCustomApi(state, facet, context, 'js');
1800
-
1801
- if (customApi) {
1802
- const apiParams = typeof mappers === 'object' && typeof mappers.customApi === 'function' && mappers.customApi(queryParams) || {};
1803
- result.payload = yield callCustomApi(customApi, apiParams);
1804
- result.duration = 1;
1805
- } else {
1806
- if (queryParams.featuredResults) {
1807
- featuredQuery = searchQuery(queryParams, true);
1808
- featuredResult = yield timedSearch(featuredQuery, queryParams.linkDepth, queryParams.projectId, queryParams.env); // eslint-disable-next-line require-atomic-updates
1809
-
1810
- queryParams.excludeIds = getItemsFromResult(featuredResult).map(fi => {
1811
- var _fi$sys;
1812
-
1813
- return fi === null || fi === void 0 ? void 0 : (_fi$sys = fi.sys) === null || _fi$sys === void 0 ? void 0 : _fi$sys.id;
1814
- }).filter(fi => typeof fi === 'string');
1815
- }
1816
-
1817
- const query = searchQuery(queryParams);
1818
- result = yield timedSearch(query, queryParams.linkDepth, queryParams.projectId, queryParams.env);
1819
- }
1820
-
1821
- const createStateFrom = {
1822
- action,
1823
- featuredResult,
1824
- pageIndex: queryParams.internalPaging && queryParams.internalPageIndex || queryParams.pageIndex,
1825
- prevResults: getResults(state, facet, action.context, 'js'),
1826
- result,
1827
- state
1828
- };
1829
- const nextAction = mapJson__default["default"](createStateFrom, facetTemplate);
1830
- yield effects.put(nextAction);
1831
- } catch (error) {
1832
- // eslint-disable-next-line import/namespace
1833
- log__namespace.error(...['Error running search saga:', error, error.stack]);
1834
- }
1835
- }
1836
-
1837
- function* preloadOtherFacets(action) {
1838
- const {
1839
- preload,
1840
- context,
1841
- facet,
1842
- debug
1843
- } = action;
1844
- const state = yield effects.select();
1845
- const currentFacet = getCurrentFacet(state);
1846
-
1847
- if (!preload && facet === currentFacet && context !== Context$1.listings) {
1848
- const allFacets = getFacets(state, 'js');
1849
- const otherFacets = Object.keys(allFacets).filter(f => f !== currentFacet);
1850
- yield effects.all(otherFacets.map((preloadFacet = '') => {
1851
- const preloadAction = { ...action,
1852
- facet: preloadFacet,
1853
- preload: true
1854
- };
1855
- const [queryParams, runSearch] = generateQueryParams(preloadAction, state);
1856
- if (debug && (debug === true || debug.preloadOtherFacets)) debugExecuteSearch(preloadAction, state);
1857
- return runSearch && effects.call(executeSearch, { ...action,
1858
- type: EXECUTE_SEARCH_PRELOAD,
1859
- preload: true,
1860
- facet: preloadFacet,
1861
- queryParams
1862
- });
1863
- }));
1864
- }
1865
- }
1866
-
1867
- function* updateCurrentTab(action) {
1868
- const {
1869
- id,
1870
- mappers
1871
- } = action;
1872
- const state = yield effects.select();
1873
- const facets = getFacets(state, 'js');
1874
- const tabs = getSearchTabs(state, 'js');
1875
- let nextFacet = tabs === null || tabs === void 0 ? void 0 : tabs[id].currentFacet;
1876
-
1877
- if (!nextFacet) {
1878
- Object.entries(facets).map(([facetName, facet]) => {
1879
- if (facet.tabId === id && (tabs === null || tabs === void 0 ? void 0 : tabs[id].defaultFacet) === facetName) nextFacet = facetName;
1880
- });
1881
- } // If the next Tab does not have a defaultFacet,
1882
- // take the first facet for that tab
1883
-
1884
-
1885
- if (!nextFacet) nextFacet = Object.entries(facets).filter(([, f]) => f.tabId === id)[0][0];
1886
- yield effects.put(withMappers(updateCurrentFacet$1(nextFacet), mappers));
1887
- }
1888
-
1889
- function* clearFilters(action) {
1890
- const {
1891
- mappers
1892
- } = action;
1893
- const uri = yield buildUri({}, mappers);
1894
- yield effects.put(navigate(uri));
1895
- }
1896
-
1897
- function* updateCurrentFacet(action) {
1898
- const {
1899
- facet,
1900
- mappers
1901
- } = action;
1902
- const pageIndex = yield effects.select(getPageIndex, facet);
1903
- const uri = yield buildUri({
1904
- facet,
1905
- pageIndex
1906
- }, mappers);
1907
- yield effects.put(navigate(uri));
1908
- }
1909
-
1910
- function* updateSearchTerm(action) {
1911
- const {
1912
- term,
1913
- mappers
1914
- } = action;
1915
- const uri = yield buildUri({
1916
- term
1917
- }, mappers);
1918
- yield effects.put(navigate(uri));
1919
- }
1920
-
1921
- function* updateSortOrder(action) {
1922
- const {
1923
- orderBy,
1924
- facet,
1925
- mappers
1926
- } = action;
1927
- const uri = yield buildUri({
1928
- orderBy,
1929
- facet
1930
- }, mappers);
1931
- yield effects.put(navigate(uri));
1932
- }
1933
-
1934
- function* updatePageIndex(action) {
1935
- const {
1936
- pageIndex,
1937
- mappers
1938
- } = action;
1939
- const uri = yield buildUri({
1940
- pageIndex
1941
- }, mappers);
1942
- yield effects.put(navigate(uri));
1943
- }
1944
-
1945
- function* applySearchFilter(action) {
1946
- const {
1947
- mappers
1948
- } = action;
1949
- const uri = yield buildUri({}, mappers);
1950
- yield effects.put(navigate(uri));
1951
- }
1952
-
1953
- function* buildUri({
1954
- facet,
1955
- orderBy,
1956
- pageIndex = 0,
1957
- term
1958
- }, mappers) {
1959
- const state = yield effects.select();
1960
- const mapUri = mappers && mappers.navigate || mapStateToSearchUri;
1961
- const uri = mapUri({
1962
- state,
1963
- facet,
1964
- orderBy,
1965
- pageIndex,
1966
- term
1967
- }); // return uri;
1968
-
1969
- return `${uri.path}${uri.search && `?${uri.search}` || ''}${uri.hash && `#${uri.hash}` || ''}`;
1970
- }
329
+ };
1971
330
 
1972
331
  const makeSelectMinilistProps = () => reselect.createSelector(state => state, (_, id) => id, (state, id) => ({
1973
- facet: getFacet(state, id, Context$1.minilist, 'js'),
1974
- filters: getFilters(state, id, Context$1.minilist, 'js'),
1975
- isLoading: getIsLoading(state, Context$1.minilist, id),
1976
- pagingInfo: getPaging(state, id, Context$1.minilist, 'js'),
1977
- results: getResults(state, id, Context$1.minilist, 'js'),
1978
- searchTerm: getSearchTerm(state)
332
+ facet: sagas.getFacet(state, id, sagas.Context.minilist, 'js'),
333
+ filters: sagas.getFilters(state, id, sagas.Context.minilist, 'js'),
334
+ isLoading: sagas.getIsLoading(state, sagas.Context.minilist, id),
335
+ pagingInfo: sagas.getPaging(state, id, sagas.Context.minilist, 'js'),
336
+ results: sagas.getResults(state, id, sagas.Context.minilist, 'js'),
337
+ searchTerm: sagas.getSearchTerm(state)
1979
338
  }));
1980
339
 
1981
340
  const useMinilist = ({
@@ -2010,9 +369,9 @@ const useMinilist = ({
2010
369
 
2011
370
  React.useEffect(() => {
2012
371
  if (id && (mapper || mappers && mappers.results)) {
2013
- dispatch(triggerSearch({
372
+ dispatch(sagas.triggerSearch({
2014
373
  config,
2015
- context: Context$1.minilist,
374
+ context: sagas.Context.minilist,
2016
375
  defaultLang,
2017
376
  facet: id,
2018
377
  mapper,
@@ -2026,7 +385,7 @@ const useMinilist = ({
2026
385
  return {
2027
386
  filters,
2028
387
  isLoading,
2029
- pagingInfo,
388
+ paging: pagingInfo,
2030
389
  results,
2031
390
  searchTerm,
2032
391
  title: facet.title
@@ -2210,7 +569,10 @@ const generateFiltersState = ({
2210
569
  // the search results during SSR without needing to fetch the filters first
2211
570
 
2212
571
 
2213
- Object.entries(filterParams).map(([paramName = '', paramValue]) => typeof paramValue === 'string' && paramValue.split(',').map(pVal => filters = addFilterItem(filters, paramName, pVal)));
572
+ Object.entries(filterParams).map(([paramName = '', paramValue]) => {
573
+ if (typeof paramValue === 'string') return paramValue.split(',').map(pVal => filters = addFilterItem(filters, paramName, pVal));
574
+ if (typeof paramValue === 'boolean') filters = addFilterItem(filters, paramName, paramValue);
575
+ });
2214
576
  return Object.fromEntries(filters);
2215
577
  };
2216
578
 
@@ -2227,22 +589,22 @@ var reducers = (config => {
2227
589
  // Add facets from SearchConfig to initialState
2228
590
  const initState = { ...initialState,
2229
591
  tabs: config.tabs,
2230
- facets: generateSearchFacets(Context$1.facets, config),
2231
- listings: generateSearchFacets(Context$1.listings, config),
2232
- minilist: generateSearchFacets(Context$1.minilist, config)
592
+ facets: generateSearchFacets(sagas.Context.facets, config),
593
+ listings: generateSearchFacets(sagas.Context.listings, config),
594
+ minilist: generateSearchFacets(sagas.Context.minilist, config)
2233
595
  };
2234
596
  return immer.produce((state = initState, action) => {
2235
597
  const context = state.context;
2236
598
  const current = context !== 'listings' ? state.currentFacet : state.currentListing;
2237
599
 
2238
600
  switch (action.type) {
2239
- case APPLY_CONFIG:
601
+ case sagas.APPLY_CONFIG:
2240
602
  {
2241
603
  state = addConfigToState(state, action);
2242
- return;
604
+ return state;
2243
605
  }
2244
606
 
2245
- case CLEAR_FILTERS:
607
+ case sagas.CLEAR_FILTERS:
2246
608
  {
2247
609
  const currentFilters = state[context][current].filters;
2248
610
  state[context][current].filters = Object.fromEntries(Object.entries(currentFilters).map(([key, filter]) => {
@@ -2257,13 +619,13 @@ var reducers = (config => {
2257
619
  return;
2258
620
  }
2259
621
 
2260
- case EXECUTE_SEARCH:
622
+ case sagas.EXECUTE_SEARCH:
2261
623
  {
2262
624
  state[action.context][action.facet].entries.isLoading = true;
2263
625
  return;
2264
626
  }
2265
627
 
2266
- case EXECUTE_SEARCH_ERROR:
628
+ case sagas.EXECUTE_SEARCH_ERROR:
2267
629
  {
2268
630
  state[action.context][action.facet].entries = { ...entries,
2269
631
  isError: true,
@@ -2272,7 +634,7 @@ var reducers = (config => {
2272
634
  return;
2273
635
  }
2274
636
 
2275
- case LOAD_FILTERS:
637
+ case sagas.LOAD_FILTERS:
2276
638
  {
2277
639
  const {
2278
640
  facetKey,
@@ -2294,8 +656,8 @@ var reducers = (config => {
2294
656
  return;
2295
657
  }
2296
658
 
2297
- case LOAD_FILTERS_ERROR:
2298
- case LOAD_FILTERS_COMPLETE:
659
+ case sagas.LOAD_FILTERS_ERROR:
660
+ case sagas.LOAD_FILTERS_COMPLETE:
2299
661
  {
2300
662
  const {
2301
663
  facetKey,
@@ -2319,7 +681,7 @@ var reducers = (config => {
2319
681
  return;
2320
682
  }
2321
683
 
2322
- case SET_ROUTE_FILTERS:
684
+ case sagas.SET_ROUTE_FILTERS:
2323
685
  {
2324
686
  const {
2325
687
  facet,
@@ -2351,12 +713,12 @@ var reducers = (config => {
2351
713
  resetCurrentFacet = state.config.isLoaded === true && !equals__default["default"](nextFilters, stateFacet.filters);
2352
714
  stateFacet = resetCurrentFacet ? resetFacet(stateFacet) : stateFacet;
2353
715
  stateFacet.filters = nextFilters;
2354
- stateFacet.queryParams.dynamicOrderBy = toArray(orderBy) || [];
716
+ stateFacet.queryParams.dynamicOrderBy = sagas.toArray(orderBy) || [];
2355
717
  return [facetName, stateFacet];
2356
718
  }));
2357
719
  state.context = context;
2358
720
  state[context] = nextFacets;
2359
- state[action.context === Context$1.facets ? 'currentFacet' : 'currentListing'] = facet;
721
+ state[action.context === sagas.Context.facets ? 'currentFacet' : 'currentListing'] = facet;
2360
722
  state.term = term;
2361
723
  state.tabs[tabId].currentFacet = facet;
2362
724
  state[context][facet].pagingInfo.pageIndex = Number(pageIndex) - 1 || (state[context][facet].queryParams.loadMorePaging ? state[context][facet].pagingInfo.pageIndex || 0 : 0);
@@ -2366,7 +728,7 @@ var reducers = (config => {
2366
728
  return;
2367
729
  }
2368
730
 
2369
- case SET_SEARCH_ENTRIES:
731
+ case sagas.SET_SEARCH_ENTRIES:
2370
732
  {
2371
733
  const thisContext = action.context || context;
2372
734
  const currentFacet = state[thisContext][action.facet];
@@ -2376,7 +738,7 @@ var reducers = (config => {
2376
738
  return;
2377
739
  }
2378
740
 
2379
- case SET_SEARCH_FILTERS:
741
+ case sagas.SET_SEARCH_FILTERS:
2380
742
  {
2381
743
  var _action$params;
2382
744
 
@@ -2389,15 +751,15 @@ var reducers = (config => {
2389
751
  isCurrentFacet: true
2390
752
  }, state);
2391
753
  const term = action === null || action === void 0 ? void 0 : (_action$params = action.params) === null || _action$params === void 0 ? void 0 : _action$params.term;
2392
- const useSearchTerm = state[action.context || Context$1.minilist][action.facet].queryParams.useSearchTerm || false;
2393
- state[action.context || Context$1.minilist][action.facet].filters = filters;
2394
- state[action.context || Context$1.minilist][action.facet].queryParams.excludeIds = action.excludeIds;
754
+ const useSearchTerm = state[action.context || sagas.Context.minilist][action.facet].queryParams.useSearchTerm || false;
755
+ state[action.context || sagas.Context.minilist][action.facet].filters = filters;
756
+ state[action.context || sagas.Context.minilist][action.facet].queryParams.excludeIds = action.excludeIds;
2395
757
  state.term = useSearchTerm ? term : state.term;
2396
758
  state.config.ssr = typeof window === 'undefined';
2397
759
  return;
2398
760
  }
2399
761
 
2400
- case UPDATE_PAGE_INDEX:
762
+ case sagas.UPDATE_PAGE_INDEX:
2401
763
  {
2402
764
  const {
2403
765
  pageIndex
@@ -2412,24 +774,33 @@ var reducers = (config => {
2412
774
  return;
2413
775
  }
2414
776
 
2415
- case UPDATE_SEARCH_TERM:
777
+ case sagas.UPDATE_SEARCH_TERM:
2416
778
  {
2417
779
  state.term = action.term;
2418
780
  state[context] = resetFacets(state, context);
2419
781
  return;
2420
782
  }
2421
783
 
2422
- case UPDATE_SELECTED_FILTERS:
784
+ case sagas.UPDATE_SELECTED_FILTERS:
2423
785
  {
2424
786
  const {
2425
787
  filter,
2426
- key
788
+ key,
789
+ isUnknownItem
2427
790
  } = action;
2428
791
  const isSingleSelect = state[context][current].filters[filter].isSingleSelect || false;
2429
792
  const isGrouped = state[context][current].filters[filter].isGrouped || false;
2430
793
  const currentItems = state[context][current].filters[filter].items;
2431
794
  if (isGrouped) state[context] = resetFacets(state, context);
2432
795
  state[context][current] = resetFacet(state[context][current]);
796
+
797
+ if (isUnknownItem && (currentItems === null || currentItems === void 0 ? void 0 : currentItems.findIndex(item => (item === null || item === void 0 ? void 0 : item.key) === key)) === -1) {
798
+ currentItems === null || currentItems === void 0 ? void 0 : currentItems.push({
799
+ key,
800
+ isSelected: false
801
+ });
802
+ }
803
+
2433
804
  state[context][current].filters[filter].items = currentItems === null || currentItems === void 0 ? void 0 : currentItems.map(item => {
2434
805
  if (item.key === key) {
2435
806
  return { ...item,
@@ -2445,7 +816,7 @@ var reducers = (config => {
2445
816
  return;
2446
817
  }
2447
818
 
2448
- case UPDATE_SORT_ORDER:
819
+ case sagas.UPDATE_SORT_ORDER:
2449
820
  {
2450
821
  const {
2451
822
  orderBy,
@@ -2453,7 +824,7 @@ var reducers = (config => {
2453
824
  } = action;
2454
825
  state[context] = resetFacets(state, context);
2455
826
  const currentFacet = facet || current;
2456
- state[context][currentFacet].queryParams.dynamicOrderBy = orderBy ? toArray(orderBy) || [] : [];
827
+ state[context][currentFacet].queryParams.dynamicOrderBy = orderBy ? sagas.toArray(orderBy) || [] : [];
2457
828
  return;
2458
829
  }
2459
830
 
@@ -2463,23 +834,25 @@ var reducers = (config => {
2463
834
  }, initState);
2464
835
  });
2465
836
 
2466
- // eslint-disable-next-line @typescript-eslint/naming-convention
2467
837
  const Context = {
2468
838
  facets: 'facets',
2469
839
  listings: 'listings',
2470
840
  minilist: 'minilist'
2471
841
  };
2472
842
 
843
+ exports.actions = sagas.actions;
844
+ exports.doSearch = sagas.doSearch;
845
+ exports.expressions = sagas.expressions;
846
+ exports.queries = sagas.queries;
847
+ exports.sagas = sagas.searchSagas;
848
+ exports.selectors = sagas.selectors;
849
+ exports.setRouteFilters = sagas.setRouteFilters;
850
+ exports.types = sagas.types;
2473
851
  exports.Context = Context;
2474
- exports.actions = actions;
2475
- exports.doSearch = doSearch;
2476
- exports.queries = queries;
2477
852
  exports.reducer = reducers;
2478
- exports.sagas = searchSagas;
2479
853
  exports.schema = schema;
2480
- exports.selectors = selectors;
2481
- exports.setRouteFilters = setRouteFilters;
2482
- exports.types = types;
854
+ exports.useFacets = useFacets;
855
+ exports.useListing = useListing;
2483
856
  exports.useMinilist = useMinilist;
2484
857
  exports.withListing = withListing;
2485
858
  exports.withSearch = withSearch;