@zengenti/contensis-react-base 4.0.0-beta.9 → 4.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +14 -1
  2. package/cjs/{App-vZrUfVgQ.js → App-Bg1MzW4V.js} +593 -110
  3. package/cjs/App-Bg1MzW4V.js.map +1 -0
  4. package/cjs/{ChangePassword.container-ECjEXixF.js → ChangePassword.container-C4Du3Wb1.js} +57 -50
  5. package/cjs/ChangePassword.container-C4Du3Wb1.js.map +1 -0
  6. package/cjs/{SSRContext-DVj_QAC1.js → ContensisDeliveryApi-MfcvdfDR.js} +32 -74
  7. package/cjs/ContensisDeliveryApi-MfcvdfDR.js.map +1 -0
  8. package/cjs/CookieConstants-DfPiWCRZ.js +12 -0
  9. package/cjs/CookieConstants-DfPiWCRZ.js.map +1 -0
  10. package/{esm/CookieHelper.class-FTURFpz3.js → cjs/CookieHelper.class-Det3qfdU.js} +4 -6
  11. package/cjs/CookieHelper.class-Det3qfdU.js.map +1 -0
  12. package/cjs/{RouteLoader-D5Yg7EB5.js → RouteLoader-DJeM8cym.js} +17 -9
  13. package/cjs/RouteLoader-DJeM8cym.js.map +1 -0
  14. package/cjs/SSRContext-tMufQDHY.js +116 -0
  15. package/cjs/SSRContext-tMufQDHY.js.map +1 -0
  16. package/cjs/ToJs-BsWqWjdm.js +23 -0
  17. package/cjs/ToJs-BsWqWjdm.js.map +1 -0
  18. package/cjs/{VersionInfo-B_dKCubg.js → VersionInfo-zFPsvS8q.js} +3 -25
  19. package/cjs/VersionInfo-zFPsvS8q.js.map +1 -0
  20. package/cjs/client.js +63 -65
  21. package/cjs/client.js.map +1 -1
  22. package/cjs/contensis-react-base.js +208 -119
  23. package/cjs/contensis-react-base.js.map +1 -1
  24. package/cjs/i18n.js +75 -0
  25. package/cjs/i18n.js.map +1 -0
  26. package/cjs/{ToJs-C9jwV7YB.js → matchGroups-dqONU-vY.js} +2 -22
  27. package/cjs/matchGroups-dqONU-vY.js.map +1 -0
  28. package/cjs/redux.js +8 -6
  29. package/cjs/redux.js.map +1 -1
  30. package/cjs/routing.js +15 -7
  31. package/cjs/routing.js.map +1 -1
  32. package/cjs/{sagas-BVX4Ps1e.js → sagas-BCy9u6zA.js} +523 -375
  33. package/cjs/sagas-BCy9u6zA.js.map +1 -0
  34. package/cjs/search.js +54 -29
  35. package/cjs/search.js.map +1 -1
  36. package/cjs/{selectors-wCs5fHD4.js → selectors-BrxJ8-F8.js} +27 -6
  37. package/cjs/selectors-BrxJ8-F8.js.map +1 -0
  38. package/cjs/selectors-DAQR0uZa.js +18 -0
  39. package/cjs/selectors-DAQR0uZa.js.map +1 -0
  40. package/cjs/slice-5xJMH24n.js +69 -0
  41. package/cjs/slice-5xJMH24n.js.map +1 -0
  42. package/cjs/{store-D07FOXvM.js → store-B7SJs5Hf.js} +64 -5
  43. package/cjs/store-B7SJs5Hf.js.map +1 -0
  44. package/cjs/urls-DGZlAs0y.js +25 -0
  45. package/cjs/urls-DGZlAs0y.js.map +1 -0
  46. package/cjs/user.js +20 -17
  47. package/cjs/user.js.map +1 -1
  48. package/cjs/util-eOjxDjxF.js +148 -0
  49. package/cjs/util-eOjxDjxF.js.map +1 -0
  50. package/cjs/util.js +80 -22
  51. package/cjs/util.js.map +1 -1
  52. package/cjs/{version-CM-bJ62L.js → version-rFG9Y6_B.js} +2 -2
  53. package/cjs/{version-CM-bJ62L.js.map → version-rFG9Y6_B.js.map} +1 -1
  54. package/cjs/{version-B7XFkBhY.js → version-yjHMrfVz.js} +15 -16
  55. package/cjs/version-yjHMrfVz.js.map +1 -0
  56. package/esm/{App-DLZweVSp.js → App-Bplaqueq.js} +554 -72
  57. package/esm/App-Bplaqueq.js.map +1 -0
  58. package/esm/{ChangePassword.container-BgzIy8dA.js → ChangePassword.container-CUBtn82K.js} +19 -13
  59. package/esm/ChangePassword.container-CUBtn82K.js.map +1 -0
  60. package/esm/{SSRContext-BE8ElZ3X.js → ContensisDeliveryApi-LWYXevZ1.js} +30 -67
  61. package/esm/ContensisDeliveryApi-LWYXevZ1.js.map +1 -0
  62. package/esm/CookieConstants-DEmbwzYr.js +7 -0
  63. package/esm/CookieConstants-DEmbwzYr.js.map +1 -0
  64. package/{cjs/CookieHelper.class-C3Eqoze9.js → esm/CookieHelper.class-C6rTRl_1.js} +2 -14
  65. package/esm/CookieHelper.class-C6rTRl_1.js.map +1 -0
  66. package/esm/{RouteLoader-xeQBXywk.js → RouteLoader-CzrlySZf.js} +14 -6
  67. package/esm/RouteLoader-CzrlySZf.js.map +1 -0
  68. package/esm/SSRContext-Bxtg1KGv.js +106 -0
  69. package/esm/SSRContext-Bxtg1KGv.js.map +1 -0
  70. package/esm/ToJs-BnRRHk6f.js +17 -0
  71. package/esm/ToJs-BnRRHk6f.js.map +1 -0
  72. package/esm/{VersionInfo-Cno7K0OA.js → VersionInfo-By2ZCZOh.js} +4 -24
  73. package/esm/VersionInfo-By2ZCZOh.js.map +1 -0
  74. package/esm/client.js +63 -64
  75. package/esm/client.js.map +1 -1
  76. package/esm/contensis-react-base.js +201 -114
  77. package/esm/contensis-react-base.js.map +1 -1
  78. package/esm/i18n.js +64 -0
  79. package/esm/i18n.js.map +1 -0
  80. package/esm/{ToJs-CNzfvyxJ.js → matchGroups-_w8BwzCC.js} +3 -18
  81. package/esm/matchGroups-_w8BwzCC.js.map +1 -0
  82. package/esm/redux.js +11 -8
  83. package/esm/redux.js.map +1 -1
  84. package/esm/routing.js +14 -7
  85. package/esm/routing.js.map +1 -1
  86. package/esm/{sagas-JI51CS37.js → sagas-Fr9yRduO.js} +511 -362
  87. package/esm/sagas-Fr9yRduO.js.map +1 -0
  88. package/esm/search.js +73 -47
  89. package/esm/search.js.map +1 -1
  90. package/esm/{selectors-DO2ocdOp.js → selectors-8ROQrTd7.js} +25 -7
  91. package/esm/selectors-8ROQrTd7.js.map +1 -0
  92. package/esm/selectors-DcmvOeX2.js +10 -0
  93. package/esm/selectors-DcmvOeX2.js.map +1 -0
  94. package/esm/slice-C6JLQik8.js +63 -0
  95. package/esm/slice-C6JLQik8.js.map +1 -0
  96. package/esm/{store-3u0RzHZ0.js → store-B4IrBYHm.js} +64 -6
  97. package/esm/store-B4IrBYHm.js.map +1 -0
  98. package/esm/urls-tLxo_skx.js +22 -0
  99. package/esm/urls-tLxo_skx.js.map +1 -0
  100. package/esm/user.js +9 -6
  101. package/esm/user.js.map +1 -1
  102. package/esm/util-Bl2u6LpY.js +136 -0
  103. package/esm/util-Bl2u6LpY.js.map +1 -0
  104. package/esm/util.js +58 -14
  105. package/esm/util.js.map +1 -1
  106. package/esm/{version-wnf-TITV.js → version-BQAL8sQO.js} +2 -2
  107. package/esm/{version-wnf-TITV.js.map → version-BQAL8sQO.js.map} +1 -1
  108. package/esm/{version-BlsI7hX2.js → version-CA9Mdm3A.js} +16 -16
  109. package/esm/version-CA9Mdm3A.js.map +1 -0
  110. package/i18n/package.json +5 -0
  111. package/models/app/pages/VersionInfo/components/VersionInfo.d.ts +1 -1
  112. package/models/app/pages/VersionInfo/components/VersionInfo.styled.d.ts +1 -2
  113. package/models/i18n/index.d.ts +5 -0
  114. package/models/i18n/redux/sagas.d.ts +19 -0
  115. package/models/i18n/redux/selectors.d.ts +11 -0
  116. package/models/i18n/redux/slice.d.ts +198 -0
  117. package/models/i18n/routes.d.ts +8 -0
  118. package/models/i18n/useI18n.hook.d.ts +20 -0
  119. package/models/index.d.ts +1 -0
  120. package/models/models/AppState.d.ts +2 -0
  121. package/models/models/ContentTypeMapping.d.ts +6 -1
  122. package/models/models/EntryMapper.d.ts +2 -1
  123. package/models/models/Locales.d.ts +11 -0
  124. package/models/models/MatchedRoute.d.ts +5 -1
  125. package/models/models/RouteComponent.d.ts +0 -1
  126. package/models/models/RouteNode.d.ts +4 -2
  127. package/models/models/SSRContext.d.ts +4 -4
  128. package/models/models/StaticRoute.d.ts +12 -1
  129. package/models/models/WithEvents.d.ts +8 -0
  130. package/models/models/config/AppConfig.d.ts +2 -0
  131. package/models/models/config/I18n.d.ts +38 -0
  132. package/models/models/config/ServerConfig.d.ts +14 -0
  133. package/models/redux/index.d.ts +2 -1
  134. package/models/redux/sagas/index.d.ts +3 -1
  135. package/models/redux/sagas/injector.d.ts +13 -0
  136. package/models/redux/store/injectors/index.d.ts +26 -0
  137. package/models/redux/store/injectors/inject.d.ts +24 -0
  138. package/models/redux/store/injectors/util.d.ts +2 -0
  139. package/models/redux/store/store.d.ts +13 -4
  140. package/models/redux/util.d.ts +1 -1
  141. package/models/routing/components/RouteLoader.d.ts +3 -3
  142. package/models/routing/httpContext.d.ts +0 -1
  143. package/models/routing/index.d.ts +1 -0
  144. package/models/routing/redux/actions.d.ts +1 -1
  145. package/models/routing/redux/invokeSearch.d.ts +22 -0
  146. package/models/routing/redux/selectors.d.ts +47 -4
  147. package/models/routing/util/expressions.d.ts +1 -1
  148. package/models/routing/util/find-contenttype-mapping.d.ts +3 -1
  149. package/models/search/containers/withListing.d.ts +1 -1
  150. package/models/search/containers/withSearch.d.ts +1 -1
  151. package/models/search/models/Queries.d.ts +3 -5
  152. package/models/search/models/Search.d.ts +43 -13
  153. package/models/search/models/SearchActions.d.ts +61 -18
  154. package/models/search/models/SearchProps.d.ts +11 -10
  155. package/models/search/models/SearchState.d.ts +23 -2
  156. package/models/search/models/SearchUtil.d.ts +3 -3
  157. package/models/search/redux/getIn.d.ts +2 -2
  158. package/models/search/redux/reducers.d.ts +3 -4
  159. package/models/search/redux/sagas.d.ts +13 -14
  160. package/models/search/redux/schema.d.ts +3 -3
  161. package/models/search/redux/selectors.d.ts +64 -42
  162. package/models/search/redux/util.d.ts +10 -1
  163. package/models/search/search/ContensisDeliveryApi.d.ts +6 -26
  164. package/models/search/search/expressions.d.ts +6 -4
  165. package/models/search/search/util.d.ts +9 -7
  166. package/models/search/transformations/state-to-queryparams.mapper.d.ts +1 -1
  167. package/models/server/features/linkdepth-api/search.d.ts +1 -1
  168. package/models/server/features/response-handler/render-stream.d.ts +2 -4
  169. package/models/server/features/static-assets/index.d.ts +4 -3
  170. package/models/server/internalServer.d.ts +1 -2
  171. package/models/server/middleware/subsiteDebug.d.ts +11 -0
  172. package/models/server/root.d.ts +3 -0
  173. package/models/server/util/bundles.d.ts +9 -9
  174. package/models/server/util/jsx.d.ts +2 -14
  175. package/models/user/components.styled/Login.styled.d.ts +1 -1
  176. package/models/user/components.styled/LoginForm.styled.d.ts +1 -1
  177. package/models/user/hocs/withRegistration.d.ts +1 -1
  178. package/models/util/CachedDeliveryApi.d.ts +8 -2
  179. package/models/util/ContensisDeliveryApi.d.ts +2 -4
  180. package/models/util/NoSSR.d.ts +6 -0
  181. package/models/util/SSRContext.d.ts +3 -19
  182. package/models/util/donotuse_useHistory.d.ts +6 -0
  183. package/models/util/errors.d.ts +16 -0
  184. package/models/util/index.d.ts +7 -2
  185. package/models/util/subsite.d.ts +12 -0
  186. package/models/util/urls.d.ts +1 -2
  187. package/models/util/useIsClient.d.ts +6 -0
  188. package/package.json +37 -39
  189. package/cjs/App-vZrUfVgQ.js.map +0 -1
  190. package/cjs/ChangePassword.container-ECjEXixF.js.map +0 -1
  191. package/cjs/CookieHelper.class-C3Eqoze9.js.map +0 -1
  192. package/cjs/RouteLoader-D5Yg7EB5.js.map +0 -1
  193. package/cjs/SSRContext-DVj_QAC1.js.map +0 -1
  194. package/cjs/ToJs-C9jwV7YB.js.map +0 -1
  195. package/cjs/VersionInfo-B_dKCubg.js.map +0 -1
  196. package/cjs/sagas-BVX4Ps1e.js.map +0 -1
  197. package/cjs/selectors-wCs5fHD4.js.map +0 -1
  198. package/cjs/store-D07FOXvM.js.map +0 -1
  199. package/cjs/version-B7XFkBhY.js.map +0 -1
  200. package/esm/App-DLZweVSp.js.map +0 -1
  201. package/esm/ChangePassword.container-BgzIy8dA.js.map +0 -1
  202. package/esm/CookieHelper.class-FTURFpz3.js.map +0 -1
  203. package/esm/RouteLoader-xeQBXywk.js.map +0 -1
  204. package/esm/SSRContext-BE8ElZ3X.js.map +0 -1
  205. package/esm/ToJs-CNzfvyxJ.js.map +0 -1
  206. package/esm/VersionInfo-Cno7K0OA.js.map +0 -1
  207. package/esm/sagas-JI51CS37.js.map +0 -1
  208. package/esm/selectors-DO2ocdOp.js.map +0 -1
  209. package/esm/store-3u0RzHZ0.js.map +0 -1
  210. package/esm/version-BlsI7hX2.js.map +0 -1
  211. package/models/redux/store/injectors.d.ts +0 -31
  212. package/models/search/search/ToJs.d.ts +0 -4
@@ -3,21 +3,34 @@
3
3
  var history$1 = require('history');
4
4
  var effects = require('@redux-saga/core/effects');
5
5
  var log = require('loglevel');
6
- var store = require('./store-D07FOXvM.js');
7
- var version = require('./version-B7XFkBhY.js');
6
+ var store = require('./store-B7SJs5Hf.js');
7
+ var version = require('./version-yjHMrfVz.js');
8
8
  var to = require('await-to-js');
9
- var selectors = require('./selectors-wCs5fHD4.js');
10
- var version$1 = require('./version-CM-bJ62L.js');
11
- var ChangePassword_container = require('./ChangePassword.container-ECjEXixF.js');
9
+ var createSagaMiddleware = require('redux-saga');
10
+ var contensisDeliveryApi = require('contensis-delivery-api');
11
+ var slice = require('./slice-5xJMH24n.js');
12
+ var selectors$1 = require('./selectors-BrxJ8-F8.js');
13
+ var version$1 = require('./version-rFG9Y6_B.js');
14
+ var ContensisDeliveryApi = require('./ContensisDeliveryApi-MfcvdfDR.js');
12
15
  var React = require('react');
13
16
  require('react-cookie');
14
17
  require('react-redux');
18
+ require('./VersionInfo-zFPsvS8q.js');
19
+ require('react-helmet-async');
15
20
  require('jsonpath-mapper');
16
- var contensisDeliveryApi = require('contensis-delivery-api');
17
- var ToJs = require('./ToJs-C9jwV7YB.js');
18
- require('query-string');
19
21
  require('react-router-dom');
20
- var RouteLoader = require('./RouteLoader-D5Yg7EB5.js');
22
+ var selectors = require('./selectors-DAQR0uZa.js');
23
+ var ChangePassword_container = require('./ChangePassword.container-C4Du3Wb1.js');
24
+ require('./sagas-BCy9u6zA.js');
25
+ require('reselect');
26
+ require('immer');
27
+ require('deep-equal');
28
+ require('deepmerge');
29
+ var util = require('./util-eOjxDjxF.js');
30
+ require('contensis-core-api');
31
+ var matchGroups = require('./matchGroups-dqONU-vY.js');
32
+ var RouteLoader = require('./RouteLoader-DJeM8cym.js');
33
+ require('query-string');
21
34
 
22
35
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
23
36
 
@@ -43,6 +56,60 @@ var log__namespace = /*#__PURE__*/_interopNamespace(log);
43
56
  var to__default = /*#__PURE__*/_interopDefault(to);
44
57
  var React__default = /*#__PURE__*/_interopDefault(React);
45
58
 
59
+ const isApiError = e => !!e && typeof e === 'object' && 'status' in e && 'statusText' in e;
60
+ const isPlainError = e => !!e && typeof e === 'object' && 'message' in e && typeof e.message === 'string';
61
+ const logError = (prefix, e) => {
62
+ var _e$data;
63
+ const message = isApiError(e) ? `${prefix} ${e.status} "${((_e$data = e.data) === null || _e$data === void 0 ? void 0 : _e$data.message) || ''}" url: ${e.url || ''}` : isPlainError(e) ? `${prefix} "${(e === null || e === void 0 ? void 0 : e.message) || e}"${e !== null && e !== void 0 && e.stack ? `\n${e.stack}` : ''}` : `${prefix} "${e}"`;
64
+ log.error(message);
65
+ };
66
+ const shorten = (str, maxLength = 120, endWeight = 0.6) => {
67
+ if (!str || str.length <= maxLength) return str;
68
+ const charsToShow = maxLength - 3;
69
+ const back = Math.floor(charsToShow * endWeight);
70
+ const front = charsToShow - back;
71
+ return `${str.slice(0, front)}...${str.slice(str.length - back)}`;
72
+ };
73
+
74
+ const deparameterise = path => {
75
+ return path.replace(/\/:\w+\??/g, '');
76
+ };
77
+
78
+ /** Create static routes for routes with specified locales */
79
+ const createLocaleRoutes = routes => {
80
+ const localeRoutes = {};
81
+ for (const route of routes.StaticRoutes) {
82
+ // If the route has defined locales, create entries for each locale
83
+ if (route.i18n && route.path) {
84
+ for (const [language, path] of Object.entries(route.i18n)) {
85
+ // We already have a locale route, so just append the language and path
86
+ const deparameterisedPath = deparameterise(route.path);
87
+ const deparameterisedLocalePath = deparameterise(path);
88
+ if (localeRoutes[deparameterisedPath]) localeRoutes[deparameterisedPath][language] = deparameterisedLocalePath;
89
+ // Otherwise, create a new entry for this route path
90
+ else localeRoutes[deparameterisedPath] = {
91
+ [language]: deparameterisedLocalePath
92
+ };
93
+ if (deparameterise(route.path) !== deparameterisedLocalePath) {
94
+ // I think we are OK to mutate here as this is only run once on app init
95
+ // we can change this if needed later
96
+ routes.StaticRoutes.push({
97
+ ...route,
98
+ path,
99
+ // Add the path with any parameters included
100
+ language,
101
+ i18n: undefined
102
+ });
103
+ } else {
104
+ // Just set the language on the existing route instead of creating a duplicate
105
+ route.language = language;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ return localeRoutes;
111
+ };
112
+
46
113
  // Create a history depending on the environment
47
114
  const selectedHistory = typeof window !== 'undefined' ? history$1.createBrowserHistory : history$1.createMemoryHistory;
48
115
  const history = (options = {}) => selectedHistory(options);
@@ -55,12 +122,17 @@ function* ensureNodeTreeSaga(action) {
55
122
  language,
56
123
  project,
57
124
  versionStatus,
125
+ subsitePath,
58
126
  treeDepth
59
127
  } = action;
60
128
  const state = yield effects.select();
61
129
  try {
62
130
  if (!version.hasNavigationTree(state)) {
63
- const nodes = yield api.getRootNode({
131
+ const nodes = subsitePath ? yield api.getNode({
132
+ path: subsitePath,
133
+ depth: treeDepth || 0,
134
+ language
135
+ }, project) : yield api.getRootNode({
64
136
  depth: treeDepth || 0,
65
137
  language
66
138
  }, versionStatus, project);
@@ -84,6 +156,238 @@ function* ensureNodeTreeSaga(action) {
84
156
  }
85
157
  }
86
158
 
159
+ const i18nSagas = [effects.takeEvery(slice.actions.INIT_LOCALES.type, getProjectLanguages), effects.takeEvery(slice.actions.UPDATE_LANGUAGE.type, updateLanguage), effects.takeEvery(slice.actions.SET_LANGUAGE.type, setLanguageRoute)];
160
+
161
+ /**
162
+ * Resolve the current route language based on the entry, node, static route or path
163
+ * Is called directly from the routing saga as soon as an entry or node has been fetched
164
+ */
165
+ function* resolveCurrentRouteLanguage({
166
+ entry,
167
+ node
168
+ }) {
169
+ var _entry$sys, _staticRoute$route;
170
+ const currentLanguage = yield effects.select(selectors.selectCurrentLanguage);
171
+ const staticRoute = yield effects.select(selectors$1.selectStaticRoute);
172
+ let nextLanguage = currentLanguage;
173
+ if (entry !== null && entry !== void 0 && (_entry$sys = entry.sys) !== null && _entry$sys !== void 0 && _entry$sys.language) nextLanguage = entry.sys.language;else if (node !== null && node !== void 0 && node.language) nextLanguage = node.language;else if (staticRoute !== null && staticRoute !== void 0 && (_staticRoute$route = staticRoute.route) !== null && _staticRoute$route !== void 0 && _staticRoute$route.language) nextLanguage = staticRoute.route.language;else {
174
+ var _currentPath$split$fi;
175
+ // attempt to infer language from the path
176
+ const currentPath = yield effects.select(selectors$1.selectCurrentPath);
177
+
178
+ // path is normally lowercase
179
+ const firstPathSegment = (_currentPath$split$fi = currentPath.split('/').find(segment => segment.length)) === null || _currentPath$split$fi === void 0 ? void 0 : _currentPath$split$fi.toLowerCase();
180
+ const locales = yield effects.select(selectors.selectLocales);
181
+ const matchedLanguage = Object.keys(locales).find(lang => lang.toLowerCase() === firstPathSegment);
182
+ // matched a supported language in the path
183
+ if (matchedLanguage) nextLanguage = matchedLanguage;else
184
+ // falling back to primary language
185
+ nextLanguage = yield effects.select(selectors.selectPrimaryLanguage);
186
+ }
187
+ if (nextLanguage && nextLanguage !== currentLanguage) {
188
+ const dictionary = yield effects.call(resolveDictionaryForLanguage, nextLanguage);
189
+ yield effects.put(slice.actions.SET_LANGUAGE({
190
+ language: nextLanguage,
191
+ dictionary
192
+ }));
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Resolve the current dictionary for route language either using a supplied resolver
198
+ * function or directly derive from the locales stored in state
199
+ * Is called directly any time the language is changed
200
+ */
201
+ function* resolveDictionaryForLanguage(language) {
202
+ let dictionary = yield effects.select(selectors.selectDictionary);
203
+ // try and resolve a dictionary for this language
204
+ const resolver = yield effects.select(selectors.selectDictionaryResolver);
205
+ if (typeof resolver === 'function') {
206
+ try {
207
+ // dynamic import of dictionary file
208
+ const loadedDictionary = yield effects.call(resolver, language);
209
+ dictionary = loadedDictionary;
210
+ } catch (error) {
211
+ console.error(`No dictionary resolved for language ${language}`, error);
212
+ }
213
+ } else {
214
+ // Load dictionary from locales in state
215
+ const locales = yield effects.select(selectors.selectLocales);
216
+ if (locales && locales[language]) {
217
+ dictionary = locales[language];
218
+ }
219
+ }
220
+ return dictionary;
221
+ }
222
+
223
+ /**
224
+ * Side effects triggered from updating the language via dispatched action
225
+ * in language switching components, including resolving the next route,
226
+ * update the dictionary and subsequently redirect if needed
227
+ */
228
+ function* updateLanguage({
229
+ payload: {
230
+ language,
231
+ redirect,
232
+ fallbackPath
233
+ }
234
+ }) {
235
+ const currentLanguage = yield effects.select(selectors.selectCurrentLanguage);
236
+ if (language === currentLanguage) {
237
+ // no change needed
238
+ return;
239
+ } else {
240
+ const dictionary = language !== currentLanguage ? yield effects.call(resolveDictionaryForLanguage, language) : yield effects.select(selectors.selectDictionary);
241
+ const uri = yield effects.call(resolveNextLanguageRoute, {
242
+ language,
243
+ redirect,
244
+ fallbackPath
245
+ });
246
+ yield effects.put(slice.actions.SET_LANGUAGE({
247
+ language,
248
+ dictionary: dictionary != null ? dictionary : undefined,
249
+ redirect: redirect !== false ? uri : undefined
250
+ }));
251
+ }
252
+ }
253
+
254
+ /** Handle any route redirection after we have set the language */
255
+ function* setLanguageRoute({
256
+ payload
257
+ }) {
258
+ if (payload !== null && payload !== void 0 && payload.redirect) {
259
+ const currentPath = yield effects.select(selectors$1.selectCurrentPath);
260
+ if (payload.redirect === currentPath) {
261
+ // already on the correct path, no need to redirect
262
+ return;
263
+ }
264
+ yield effects.put(selectors$1.setRoute(payload.redirect));
265
+ }
266
+ }
267
+
268
+ /** Determine the correct route uri when the language changes */
269
+ function* resolveNextLanguageRoute({
270
+ language,
271
+ redirect,
272
+ fallbackPath
273
+ }) {
274
+ // have they supplied the route to go to?
275
+ if (typeof redirect === 'string') {
276
+ return redirect;
277
+ }
278
+
279
+ // is this an entry or a static route?
280
+ const availableLanguages = yield effects.select(selectors$1.selectRouteEntryAvailableLanguages);
281
+ if (availableLanguages.find(l => l.toLowerCase() === language.toLowerCase())) {
282
+ // if entry, get the uri for this language variation from the api
283
+ const entryUri = yield effects.call(getEntryUriForLanguage, {
284
+ entryId: yield effects.select(selectors$1.selectRouteEntryID),
285
+ language
286
+ });
287
+ if (entryUri) {
288
+ return entryUri;
289
+ }
290
+ }
291
+
292
+ // if static route, get the uri from the routes config
293
+ const staticRouteUri = yield effects.call(getStaticRouteUri, {
294
+ language
295
+ });
296
+ if (staticRouteUri) {
297
+ return staticRouteUri;
298
+ }
299
+
300
+ // if all else fails, fallback to the supplied fallback path or homepage
301
+ return fallbackPath || `/${language.toLowerCase()}`;
302
+ }
303
+
304
+ /** Check any current static route for a language variation we have stored in i18n.routes */
305
+ function* getStaticRouteUri({
306
+ language
307
+ }) {
308
+ const staticRoute = yield effects.select(selectors$1.selectStaticRoute);
309
+ if (staticRoute !== null && staticRoute !== void 0 && staticRoute.route.path) {
310
+ var _Object$entries$find;
311
+ // Routes can have parameters such as `/:facet?` we need to deparameterise
312
+ // so we can check against our stored locale routes
313
+ const deparameterisedPath = deparameterise(staticRoute.route.path);
314
+ const localeRoutes = yield effects.select(selectors.selectLocaleRoutes);
315
+ const originalPath = (_Object$entries$find = Object.entries(localeRoutes || {}).find(([, locales]) => Object.values(locales).includes(deparameterisedPath))) === null || _Object$entries$find === void 0 ? void 0 : _Object$entries$find[0];
316
+ const routeLocales = localeRoutes[deparameterisedPath] || localeRoutes[originalPath || ''];
317
+ const routeUri = routeLocales === null || routeLocales === void 0 ? void 0 : routeLocales[language];
318
+ return routeUri;
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Run when the app initiates locales, populating supported languages from the config
324
+ * or fetching from the project if not provided
325
+ */
326
+ function* getProjectLanguages({
327
+ payload
328
+ }) {
329
+ const stateLocales = yield effects.select(selectors.selectLocales);
330
+ if (stateLocales && Object.keys(stateLocales).length > 0)
331
+ // Locales already set in state, no need to fetch again
332
+ return;
333
+ const locales = {};
334
+ let primaryLanguage = payload.primaryLanguage;
335
+ const supportedLanguages = [...(payload.supportedLanguages || [])];
336
+ if (supportedLanguages !== null && supportedLanguages !== void 0 && supportedLanguages.length) {
337
+ // If supported languages are provided in config, use these
338
+ for (const supportedLanguage of supportedLanguages) {
339
+ locales[supportedLanguage] = {};
340
+ }
341
+ } else {
342
+ // Fallback to getting languages from the project
343
+ const [error, project] = yield to__default.default(ContensisDeliveryApi.cachedSearch.getClient().project.get());
344
+ if (error) {
345
+ console.error('Problem fetching project languages:', error);
346
+ } else if (project) {
347
+ var _project$primaryLangu;
348
+ for (const supportedLanguage of project.supportedLanguages || []) {
349
+ locales[supportedLanguage] = {};
350
+ supportedLanguages.push(supportedLanguage);
351
+ }
352
+ // Set primary language from project if we have it
353
+ primaryLanguage = (_project$primaryLangu = project.primaryLanguage) != null ? _project$primaryLangu : primaryLanguage;
354
+ }
355
+ }
356
+ if (Object.keys(locales).length === 0) {
357
+ // Ensure at least the primary language is included
358
+ locales[payload.primaryLanguage] = {};
359
+ supportedLanguages.push(payload.primaryLanguage);
360
+ }
361
+
362
+ // Only commit if we have locales to set or we will end up in an infinite loop
363
+ if (Object.keys(locales).length) yield effects.put(slice.actions.SET_LOCALES({
364
+ ...payload,
365
+ primaryLanguage,
366
+ supportedLanguages,
367
+ locales
368
+ }));
369
+ }
370
+
371
+ /**
372
+ * Run a Delivery API query to get the uri for the chosen language variation of this entryId
373
+ * */
374
+ function* getEntryUriForLanguage({
375
+ entryId,
376
+ language
377
+ }) {
378
+ try {
379
+ const versionStatus = yield effects.select(version$1.selectVersionStatus);
380
+ const query = new contensisDeliveryApi.Query(contensisDeliveryApi.Op.equalTo('sys.id', entryId), contensisDeliveryApi.Op.equalTo('sys.language', language), contensisDeliveryApi.Op.equalTo('sys.versionStatus', versionStatus));
381
+ query.fields = ['sys.uri'];
382
+ query.pageSize = 1;
383
+ const result = yield ContensisDeliveryApi.cachedSearch.search(query);
384
+ return result.items.length ? result.items[0].sys.uri : null;
385
+ } catch (error) {
386
+ console.error('Error fetching language variations:', error);
387
+ yield effects.put(slice.actions.GET_ENTRY_URI_ERROR(error));
388
+ }
389
+ }
390
+
87
391
  const sys = {
88
392
  versionStatus: 'sys.versionStatus'
89
393
  };
@@ -106,7 +410,89 @@ const routeEntryByFieldsQuery = (id, language = 'en-GB', contentTypeId = '', fie
106
410
  return query;
107
411
  };
108
412
 
109
- const routingSagas = [effects.takeEvery(selectors.SET_NAVIGATION_PATH, getRouteSaga), effects.takeEvery(selectors.SET_ROUTE, setRouteSaga)];
413
+ function* reduxInjectorSaga(injectorFn) {
414
+ if (typeof injectorFn === 'function') {
415
+ const {
416
+ key,
417
+ reducer,
418
+ saga
419
+ } = yield injectorFn();
420
+ version.injectRedux({
421
+ key,
422
+ reducer,
423
+ saga
424
+ });
425
+ }
426
+ }
427
+
428
+ /**
429
+ * @description Asynchronously load and inject assets related to Search
430
+ */
431
+ const importSearchAssets = () => Promise.resolve().then(function () { return require('./search.js'); });
432
+
433
+ /**
434
+ * Invokes the Search saga if:
435
+ * - `searchOptions` is present on `staticRoute` or `contentTypeRoute`
436
+ * - `searchOptions` is provided by the consumer app
437
+ * - and path starts with one of `onPaths: ['/search']`
438
+ * - or a `facet` or `listingType` is present in provided `searchOptions`
439
+ *
440
+ * A `config` is required if we want to inject the redux reducer here, sagas are injected automatically
441
+ */
442
+ function* handleSearchSaga({
443
+ location,
444
+ params,
445
+ routeSearchOptions,
446
+ searchOptions,
447
+ ssr
448
+ }) {
449
+ // Merge supplied mappers with route-supplied mappers taking precedence
450
+ const mappers = {
451
+ results: e => e,
452
+ ...((searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.mappers) || {}),
453
+ ...((routeSearchOptions === null || routeSearchOptions === void 0 ? void 0 : routeSearchOptions.mappers) || {})
454
+ };
455
+
456
+ // Merge all other search options with route-supplied options taking precedence
457
+ const {
458
+ onPaths = ['/search'],
459
+ ...searchOpts
460
+ } = {
461
+ ...(routeSearchOptions || {}),
462
+ ...(searchOptions || {})
463
+ };
464
+
465
+ // Check do we meet conditions to run the search saga
466
+ const invokeSearch = onPaths.find(p => location.pathname.startsWith(p)) || searchOpts.composition || searchOpts.facet || searchOpts.listingType;
467
+
468
+ // An empty routeSearchOptions object can be used to import assets and load config for a minilist
469
+ const importAssets = routeSearchOptions;
470
+ if (importAssets || invokeSearch) {
471
+ // Async load search assets
472
+ const {
473
+ reducer,
474
+ sagas,
475
+ setRouteFilters
476
+ } = yield importSearchAssets();
477
+
478
+ // Inject search reducer and sagas
479
+ yield effects.call(reduxInjectorSaga, async () => ({
480
+ key: 'search',
481
+ reducer: searchOpts.config && reducer(searchOpts.config),
482
+ saga: sagas
483
+ }));
484
+ if (invokeSearch) yield effects.call(setRouteFilters, {
485
+ params,
486
+ ssr,
487
+ ...searchOpts,
488
+ mappers
489
+ });
490
+ }
491
+ }
492
+
493
+ const error = (e, message) => logError(`[routeSaga]${message ? ` ${message}` : ''}`, e);
494
+ let livePreviewTask = null;
495
+ const routingSagas = [effects.takeEvery(selectors$1.SET_NAVIGATION_PATH, getRouteSaga), effects.takeEvery(selectors$1.SET_ROUTE, setRouteSaga)];
110
496
 
111
497
  /**
112
498
  * To navigate / push a specific route via redux middleware
@@ -124,7 +510,7 @@ function* setRouteSaga(action) {
124
510
  function* getRouteSaga(action) {
125
511
  let entry = null;
126
512
  try {
127
- var _staticRoute$route, _staticRoute$route2, _staticRoute$route3, _staticRoute$route4, _appsays, _appsays2, _appsays3, _pathNode3, _pathNode4;
513
+ var _staticRoute$route, _staticRoute$route2, _staticRoute$route3, _staticRoute$route4, _appsays, _appsays2, _appsays3, _pathNode3, _pathNode4, _pathNode5;
128
514
  const {
129
515
  withEvents,
130
516
  routes: {
@@ -133,7 +519,8 @@ function* getRouteSaga(action) {
133
519
  staticRoute,
134
520
  // get api instance from ssr context that is connected to the specific request in ssr
135
521
  ssr: {
136
- api
522
+ api,
523
+ subsitePath
137
524
  }
138
525
  } = action;
139
526
 
@@ -150,7 +537,12 @@ function* getRouteSaga(action) {
150
537
  // These variables are the return values from
151
538
  // calls to withEvents.onRouteLoad and onRouteLoaded
152
539
  let appsays,
153
- requireLogin = false;
540
+ requireLogin = false,
541
+ searchOptions = false;
542
+
543
+ // Route parameters are used for driving search options and live preview functionality,
544
+ // and are passed to the consuming app via withEvents hooks
545
+ const params = util.routeParams(staticRoute, action.location);
154
546
  if (withEvents && withEvents.onRouteLoad) {
155
547
  appsays = yield withEvents.onRouteLoad(action);
156
548
  }
@@ -167,15 +559,30 @@ function* getRouteSaga(action) {
167
559
  const entryFieldLinkDepths = (_appsays = appsays) === null || _appsays === void 0 ? void 0 : _appsays.entryFieldLinkDepths;
168
560
  const setStaticRouteLimits = typeof linkDepth !== 'undefined' || fields || fieldLinkDepths;
169
561
  const setContentTypeLimits = !!ContentTypeMappings.find(ct => ct.fields || ct.linkDepth || ct.nodeOptions || ct.fieldLinkDepths);
562
+
563
+ // Limits set in a static route take priority over limits in a content type mapping
564
+ // If we have limits set in:
565
+ // - a matched static route - set them here to resolve everything with the initial node upfront
566
+ // - any content type mapping - we set defaults for the initial node resolve then
567
+ // - identify the contentTypeId and locate the content type mapping
568
+ // - perform a second search query with the limits applied from the content type mapping
569
+ // If no limits are set in route configuration:
570
+ // - fall back to entryLinkDepth and entryFieldLinkDepths provided by the app in `onRouteLoad` event
571
+ // - or default to entryLinkDepth of 2 with all fields (default for legacy `/preview` endpoints)
572
+ fields = setStaticRouteLimits ? fields || '*' : setContentTypeLimits ? ['sys.contentTypeId', 'sys.id'] : '*';
573
+ linkDepth = setStaticRouteLimits && typeof linkDepth !== 'undefined' ? linkDepth : setContentTypeLimits ? 0 : entryLinkDepth;
574
+ fieldLinkDepths = setStaticRouteLimits ? fieldLinkDepths : setContentTypeLimits ? undefined : entryFieldLinkDepths;
170
575
  const state = yield effects.select();
171
- const routeEntry = selectors.selectRouteEntry(state, 'js');
172
- const routeNode = selectors.selectCurrentNode(state, 'js');
576
+ const routeEntry = selectors$1.selectRouteEntry(state, 'js');
577
+ const routeNode = selectors$1.selectCurrentNode(state, 'js');
173
578
  const currentPath = action.path; //selectCurrentPath(state);
579
+ const contentPath = action.contentPath;
174
580
  const deliveryApiStatus = version$1.selectVersionStatus(state);
175
- const project = selectors.selectCurrentProject(state);
581
+ const project = selectors$1.selectCurrentProject(state);
176
582
  // const isHome = currentPath === '/';
177
583
  const isPreview = currentPath && currentPath.startsWith('/preview/');
178
- const defaultLang = appsays && appsays.defaultLang || 'en-GB';
584
+ const currentLanguage = selectors.selectCurrentLanguage(state);
585
+ const defaultLang = appsays && appsays.defaultLang || currentLanguage || 'en-GB';
179
586
  if (!isPreview && ((_appsays2 = appsays) !== null && _appsays2 !== void 0 && _appsays2.customRouting || staticRoute && !staticRoute.route.fetchNode || routeEntry && action.statePath === action.path && ((_appsays3 = appsays) === null || _appsays3 === void 0 ? void 0 : _appsays3.refetchNode) !== true)) {
180
587
  var _staticRoute$route5;
181
588
  // To prevent erroneous 404s and wasted network calls, this covers
@@ -188,21 +595,25 @@ function* getRouteSaga(action) {
188
595
  entry: null
189
596
  };
190
597
  pathNode.entry = entry = routeEntry;
191
- //Do nothing, the entry is allready the right one.
192
- // yield put({
193
- // type: SET_ENTRY,
194
- // entry,
195
- // node: routeNode,
196
- // isLoading: false,
197
- // });
198
598
  yield effects.put({
199
- type: selectors.UPDATE_LOADING_STATE,
599
+ type: selectors$1.UPDATE_LOADING_STATE,
200
600
  isLoading: false
201
601
  });
202
- } else yield effects.call(setRouteEntry, currentPath, routeEntry, yield effects.select(selectors.selectCurrentNode), yield effects.select(selectors.selectCurrentAncestors), yield effects.select(selectors.selectCurrentSiblings));
602
+ if (params.livePreview && typeof window !== 'undefined') {
603
+ var _contentTypeMapping, _contentTypeMapping2, _contentTypeMapping3;
604
+ // Update the "limits" (fields, fieldLinkDepths and linkDepth)
605
+ // used in route resolution (likely SSR) based on the entry's content type mapping
606
+ // so that we can pass the correct limits to live preview parent
607
+ contentTypeMapping = ChangePassword_container.findContentTypeMapping(ContentTypeMappings, entry.sys.contentTypeId);
608
+ // Static route limits override content type mapping limits
609
+ fields = setStaticRouteLimits ? fields || '*' : ((_contentTypeMapping = contentTypeMapping) === null || _contentTypeMapping === void 0 ? void 0 : _contentTypeMapping.fields) || fields;
610
+ linkDepth = setStaticRouteLimits ? linkDepth || 0 : typeof ((_contentTypeMapping2 = contentTypeMapping) === null || _contentTypeMapping2 === void 0 ? void 0 : _contentTypeMapping2.linkDepth) !== 'undefined' ? contentTypeMapping.linkDepth : linkDepth;
611
+ fieldLinkDepths = setStaticRouteLimits ? fieldLinkDepths : ((_contentTypeMapping3 = contentTypeMapping) === null || _contentTypeMapping3 === void 0 ? void 0 : _contentTypeMapping3.fieldLinkDepths) || fieldLinkDepths;
612
+ }
613
+ } else yield effects.call(setRouteEntry, currentPath, routeEntry, yield effects.select(selectors$1.selectCurrentNode), yield effects.select(selectors$1.selectCurrentAncestors), yield effects.select(selectors$1.selectCurrentSiblings));
203
614
  } else {
204
615
  var _staticRoute$route6;
205
- // Handle preview routes
616
+ // Handle preview routes (legacy - can we remove?)
206
617
  if (isPreview) {
207
618
  let splitPath = currentPath.split('/');
208
619
  let entryGuid = splitPath[2];
@@ -215,7 +626,6 @@ function* getRouteSaga(action) {
215
626
  // for previewing entries as it gives a response of []
216
627
  // -- apparently it is not correct to request latest content
217
628
  // with Node API
218
-
219
629
  let previewEntry = yield api.getClient(deliveryApiStatus, project).entries.get({
220
630
  id: entryGuid,
221
631
  language,
@@ -238,11 +648,13 @@ function* getRouteSaga(action) {
238
648
  // Resolve the complete entry with the node if we are setting limits in a static route
239
649
  [nodeError, pathNode] = yield to__default.default(api.getNode({
240
650
  depth: 0,
241
- path: currentPath,
242
- entryFields: setStaticRouteLimits ? fields || '*' : setContentTypeLimits ? ['sys.contentTypeId', 'sys.id'] : '*',
243
- entryLinkDepth: setStaticRouteLimits && typeof linkDepth !== 'undefined' ? linkDepth : entryLinkDepth || 0,
244
- entryFieldLinkDepths: setStaticRouteLimits ? fieldLinkDepths : setContentTypeLimits ? undefined : entryFieldLinkDepths,
245
- language: defaultLang,
651
+ path: contentPath,
652
+ entryFields: fields,
653
+ entryLinkDepth: linkDepth,
654
+ entryFieldLinkDepths: fieldLinkDepths,
655
+ // language parameter is not used when resolving a node by path
656
+ // https://www.contensis.com/help-and-docs/apis/delivery-http/navigation/nodes/get-a-node-by-path
657
+ // language: defaultLang,
246
658
  versionStatus: deliveryApiStatus
247
659
  }, project));
248
660
  if (nodeError) {
@@ -292,10 +704,10 @@ function* getRouteSaga(action) {
292
704
  if (!setStaticRouteLimits) ({
293
705
  fieldLinkDepths,
294
706
  fields,
295
- linkDepth
707
+ linkDepth = 0
296
708
  } = contentTypeMapping || {});
297
709
  const query = routeEntryByFieldsQuery(pathNode.entry.sys.id, pathNode.entry.sys.language, pathNode.entry.sys.contentTypeId, fields, fieldLinkDepths, deliveryApiStatus);
298
- const payload = yield api.search(query, typeof linkDepth !== 'undefined' ? linkDepth : entryLinkDepth || 0, project);
710
+ const payload = yield api.search(query, linkDepth, project);
299
711
  if ((payload === null || payload === void 0 || (_payload$items = payload.items) === null || _payload$items === void 0 ? void 0 : _payload$items.length) > 0) {
300
712
  pathNode.entry = entry = payload.items[0];
301
713
  }
@@ -309,25 +721,42 @@ function* getRouteSaga(action) {
309
721
  appsays,
310
722
  contentTypeMapping: contentTypeMapping || (staticRoute === null || staticRoute === void 0 || (_staticRoute$route6 = staticRoute.route) === null || _staticRoute$route6 === void 0 ? void 0 : _staticRoute$route6.fetchNode) || {},
311
723
  language: defaultLang,
312
- path: currentPath,
724
+ path: contentPath,
313
725
  pathNode,
314
726
  project,
727
+ subsitePath,
315
728
  versionStatus: deliveryApiStatus
316
729
  });
317
730
  if (children) pathNode.children = children;
318
731
  }
319
- const resolvedContentTypeMapping = ChangePassword_container.findContentTypeMapping(ContentTypeMappings, (_pathNode3 = pathNode) === null || _pathNode3 === void 0 || (_pathNode3 = _pathNode3.entry) === null || _pathNode3 === void 0 || (_pathNode3 = _pathNode3.sys) === null || _pathNode3 === void 0 ? void 0 : _pathNode3.contentTypeId) || {};
732
+
733
+ // We initially listened for SET_ENTRY to complete before
734
+ // resolving the current route language, but this meant
735
+ // that the language change was not captured in time for the SSR response
736
+ yield effects.call(resolveCurrentRouteLanguage, {
737
+ entry: (_pathNode3 = pathNode) === null || _pathNode3 === void 0 ? void 0 : _pathNode3.entry,
738
+ node: pathNode
739
+ });
740
+ const contentTypeRoute = ChangePassword_container.findContentTypeMapping(ContentTypeMappings, (_pathNode4 = pathNode) === null || _pathNode4 === void 0 || (_pathNode4 = _pathNode4.entry) === null || _pathNode4 === void 0 || (_pathNode4 = _pathNode4.sys) === null || _pathNode4 === void 0 ? void 0 : _pathNode4.contentTypeId);
320
741
 
321
742
  // Inject redux { key, reducer, saga } provided by ContentTypeMapping
322
- if (resolvedContentTypeMapping.injectRedux) yield effects.call(reduxInjectorSaga, resolvedContentTypeMapping.injectRedux);
743
+ if (contentTypeRoute !== null && contentTypeRoute !== void 0 && contentTypeRoute.injectRedux) yield effects.call(reduxInjectorSaga, contentTypeRoute.injectRedux);
744
+
745
+ // Have we defined search options in the route configuration (for triggering search)
746
+ const routeSearchOptions = ChangePassword_container.getSearchOptions(staticRoute, contentTypeRoute);
323
747
  if (withEvents && withEvents.onRouteLoaded) {
324
748
  // Check if the app has provided a requireLogin boolean flag or groups array
325
749
  // in addition to checking if requireLogin is set in the route definition
750
+ // The app can provide an object to invoke the search saga
326
751
  ({
327
- requireLogin
752
+ requireLogin,
753
+ searchOptions
328
754
  } = (yield withEvents.onRouteLoaded({
329
755
  ...action,
330
- entry
756
+ contentTypeRoute,
757
+ entry,
758
+ params,
759
+ searchOptions: routeSearchOptions
331
760
  })) || {});
332
761
  }
333
762
  if (requireLogin !== false) {
@@ -338,22 +767,88 @@ function* getRouteSaga(action) {
338
767
  requireLogin
339
768
  });
340
769
  }
770
+ if (searchOptions || routeSearchOptions) yield effects.call(handleSearchSaga, {
771
+ ...action,
772
+ params,
773
+ routeSearchOptions,
774
+ searchOptions
775
+ });
341
776
  if (!appsays || !appsays.preventScrollTop) {
342
777
  // Scroll into View
343
778
  if (typeof window !== 'undefined') window.scrollTo(0, 0);
344
779
  }
345
- if ((_pathNode4 = pathNode) !== null && _pathNode4 !== void 0 && (_pathNode4 = _pathNode4.entry) !== null && _pathNode4 !== void 0 && (_pathNode4 = _pathNode4.sys) !== null && _pathNode4 !== void 0 && _pathNode4.id) {
780
+ if ((_pathNode5 = pathNode) !== null && _pathNode5 !== void 0 && (_pathNode5 = _pathNode5.entry) !== null && _pathNode5 !== void 0 && (_pathNode5 = _pathNode5.sys) !== null && _pathNode5 !== void 0 && _pathNode5.id) {
346
781
  var _appsays4;
782
+ entryMapper = entryMapper || (contentTypeRoute === null || contentTypeRoute === void 0 ? void 0 : contentTypeRoute.entryMapper);
783
+ if (params.livePreview && typeof window !== 'undefined') {
784
+ if (livePreviewTask) yield effects.cancel(livePreviewTask);
785
+ livePreviewTask = yield effects.fork(watchLivePreviewSaga, {
786
+ currentPath,
787
+ entry,
788
+ entryMapper,
789
+ pathNode,
790
+ limits: {
791
+ fields,
792
+ fieldLinkDepths,
793
+ linkDepth
794
+ }
795
+ });
796
+ }
347
797
  entry = pathNode.entry;
348
- yield effects.call(setRouteEntry, currentPath, entry, pathNode, ancestors, siblings, entryMapper || resolvedContentTypeMapping.entryMapper, false, (_appsays4 = appsays) === null || _appsays4 === void 0 ? void 0 : _appsays4.refetchNode);
798
+ yield effects.call(setRouteEntry, currentPath, entry, pathNode, ancestors, siblings, entryMapper, false, (_appsays4 = appsays) === null || _appsays4 === void 0 ? void 0 : _appsays4.refetchNode);
349
799
  } else {
350
800
  if (staticRoute) yield effects.call(setRouteEntry, currentPath, null, pathNode, ancestors, siblings);else yield effects.call(do404);
351
801
  }
352
802
  } catch (e) {
353
- log__namespace.error(...['Error running route saga:', e, e.stack]);
803
+ error(e);
354
804
  yield effects.call(do500, e);
355
805
  }
356
806
  }
807
+ function createLivePreviewChannel() {
808
+ return createSagaMiddleware.eventChannel(emit => {
809
+ const handler = e => {
810
+ var _e$data;
811
+ // console.log('Received message in live preview channel', e.data);
812
+ if ((_e$data = e.data) !== null && _e$data !== void 0 && (_e$data = _e$data.type) !== null && _e$data !== void 0 && _e$data.startsWith('LIVE_ENTRY_')) emit(e.data);
813
+ };
814
+ window.addEventListener('message', handler);
815
+ return () => window.removeEventListener('message', handler);
816
+ });
817
+ }
818
+ function* watchLivePreviewSaga(context) {
819
+ var _parent;
820
+ const channel = createLivePreviewChannel();
821
+ const routeLoadOptions = {
822
+ type: 'LIVE_ENTRY_ROUTE_LOAD_OPTIONS',
823
+ payload: context.limits
824
+ };
825
+ if (util.routeParams().debug) routeLoadOptions.debug = context.pathNode;
826
+ (_parent = parent) === null || _parent === void 0 || _parent.postMessage(routeLoadOptions, '*');
827
+ try {
828
+ while (true) {
829
+ const data = yield effects.take(channel);
830
+ let entry = yield effects.select(selectors$1.selectRouteEntry);
831
+ if (data.type === 'LIVE_ENTRY_RESET') {
832
+ console.log('Resetting live preview entry to original route entry');
833
+ entry = context.entry;
834
+ } else if (data.type === 'LIVE_ENTRY_UPDATE') {
835
+ console.log('Handling live preview update', data);
836
+ entry = {
837
+ ...entry,
838
+ ...data.payload
839
+ };
840
+ }
841
+ yield effects.call(setRouteEntry, context.currentPath, entry, context.pathNode, null,
842
+ // ancestors unchanged
843
+ null,
844
+ // siblings unchanged
845
+ context.entryMapper, false, true // we need to remap the entry here
846
+ );
847
+ }
848
+ } finally {
849
+ if (yield effects.cancelled()) channel.close();
850
+ }
851
+ }
357
852
  function* resolveCurrentNodeOrdinates(action) {
358
853
  const {
359
854
  api,
@@ -363,6 +858,7 @@ function* resolveCurrentNodeOrdinates(action) {
363
858
  path,
364
859
  pathNode,
365
860
  project,
861
+ subsitePath,
366
862
  versionStatus
367
863
  } = action;
368
864
  const apiCall = [() => null, () => null, () => null, () => null];
@@ -385,10 +881,11 @@ function* resolveCurrentNodeOrdinates(action) {
385
881
  return yield api.getAncestors({
386
882
  id: pathNode.id,
387
883
  language,
388
- versionStatus
884
+ versionStatus,
885
+ startLevel: (subsitePath || '').split('/').length
389
886
  }, project);
390
887
  } catch (ex) {
391
- log__namespace.info('Problem fetching ancestors', ex);
888
+ error(ex, 'Problem fetching ancestors');
392
889
  return [];
393
890
  }
394
891
  };
@@ -408,7 +905,7 @@ function* resolveCurrentNodeOrdinates(action) {
408
905
  versionStatus
409
906
  }, project);
410
907
  } catch (ex) {
411
- log__namespace.info('Problem fetching children', ex);
908
+ error(ex, 'Problem fetching children');
412
909
  return [];
413
910
  }
414
911
  };
@@ -427,7 +924,7 @@ function* resolveCurrentNodeOrdinates(action) {
427
924
  versionStatus
428
925
  }, project);
429
926
  } catch (ex) {
430
- log__namespace.info('Problem fetching siblings', ex);
927
+ error(ex, 'Problem fetching siblings');
431
928
  return [];
432
929
  }
433
930
  };
@@ -459,16 +956,16 @@ function* setRouteEntry(currentPath, entry, node, ancestors, siblings, entryMapp
459
956
  // Update a window global to provide the preview toolbar
460
957
  // an updated entry id in client-side navigation
461
958
  if (typeof window !== 'undefined') window.ContensisEntryId = entrySys.id;
462
- const currentEntryId = yield effects.select(selectors.selectRouteEntryEntryId);
463
- const currentEntryLang = yield effects.select(selectors.selectRouteEntryLanguage);
464
- const mappedEntry = !entryMapper ? null : currentEntryId === entrySys.id && currentEntryLang === entrySys.language && remapEntry === false ? (yield effects.select(selectors.selectMappedEntry, 'js')) || {} : yield mapRouteEntry(entryMapper, {
959
+ const currentEntryId = yield effects.select(selectors$1.selectRouteEntryEntryId);
960
+ const currentEntryLang = yield effects.select(selectors$1.selectRouteEntryLanguage);
961
+ const mappedEntry = !entryMapper ? null : currentEntryId === entrySys.id && currentEntryLang === entrySys.language && remapEntry === false ? (yield effects.select(selectors$1.selectMappedEntry, 'js')) || {} : yield mapRouteEntry(entryMapper, {
465
962
  ...node,
466
963
  entry,
467
964
  ancestors,
468
965
  siblings
469
966
  });
470
967
  yield effects.all([effects.put({
471
- type: selectors.SET_ENTRY,
968
+ type: selectors$1.SET_ENTRY,
472
969
  id: entrySys.id,
473
970
  currentPath,
474
971
  entry,
@@ -476,10 +973,10 @@ function* setRouteEntry(currentPath, entry, node, ancestors, siblings, entryMapp
476
973
  node,
477
974
  notFound
478
975
  }), ancestors && effects.put({
479
- type: selectors.SET_ANCESTORS,
976
+ type: selectors$1.SET_ANCESTORS,
480
977
  ancestors
481
978
  }), siblings && effects.put({
482
- type: selectors.SET_SIBLINGS,
979
+ type: selectors$1.SET_SIBLINGS,
483
980
  siblings
484
981
  })]);
485
982
  }
@@ -491,7 +988,7 @@ function* mapRouteEntry(entryMapper, node) {
491
988
  return mappedEntry;
492
989
  }
493
990
  } catch (e) {
494
- log__namespace.error(...['Error running entryMapper:', e, e.stack]);
991
+ error(e, 'Error in entryMapper:');
495
992
  throw e;
496
993
  }
497
994
  return;
@@ -499,14 +996,14 @@ function* mapRouteEntry(entryMapper, node) {
499
996
  function* do404() {
500
997
  yield effects.call(clientReloadHitServer);
501
998
  yield effects.put({
502
- type: selectors.SET_ENTRY,
999
+ type: selectors$1.SET_ENTRY,
503
1000
  id: null,
504
1001
  entry: null,
505
1002
  notFound: true
506
1003
  });
507
1004
  }
508
1005
  function* clientReloadHitServer() {
509
- const stateEntry = yield effects.select(selectors.selectRouteEntry);
1006
+ const stateEntry = yield effects.select(selectors$1.selectRouteEntry);
510
1007
 
511
1008
  // If in client and there is a stateEntry.sys field reload the page,
512
1009
  // on the 2nd load stateEntry.sys should be null at this point,
@@ -517,7 +1014,7 @@ function* clientReloadHitServer() {
517
1014
  }
518
1015
  function* do500(error) {
519
1016
  yield effects.put({
520
- type: selectors.SET_ENTRY,
1017
+ type: selectors$1.SET_ENTRY,
521
1018
  id: null,
522
1019
  entry: null,
523
1020
  notFound: true,
@@ -526,22 +1023,8 @@ function* do500(error) {
526
1023
  statusCode: error && error.status ? error.status : 500
527
1024
  });
528
1025
  }
529
- function* reduxInjectorSaga(injectorFn) {
530
- if (typeof injectorFn === 'function') {
531
- const {
532
- key,
533
- reducer,
534
- saga
535
- } = yield injectorFn();
536
- version.injectRedux({
537
- key,
538
- reducer,
539
- saga
540
- });
541
- }
542
- }
543
1026
 
544
- const registerSagas = [effects.takeEvery(selectors.REGISTER_USER, registerSaga), effects.takeEvery(selectors.REGISTER_USER_SUCCESS, redirectSaga)];
1027
+ const registerSagas = [effects.takeEvery(selectors$1.REGISTER_USER, registerSaga), effects.takeEvery(selectors$1.REGISTER_USER_SUCCESS, redirectSaga)];
545
1028
  function* registerSaga({
546
1029
  user,
547
1030
  mappers
@@ -573,13 +1056,13 @@ function* registerSaga({
573
1056
  }
574
1057
  // Update user object with mappedResponse or responseBody
575
1058
  yield effects.put({
576
- type: selectors.REGISTER_USER_SUCCESS,
1059
+ type: selectors$1.REGISTER_USER_SUCCESS,
577
1060
  user: mappedResponse || responseBody
578
1061
  });
579
1062
  } else {
580
1063
  // OK response but unable to parse the response body
581
1064
  yield effects.put({
582
- type: selectors.REGISTER_USER_FAILED,
1065
+ type: selectors$1.REGISTER_USER_FAILED,
583
1066
  error: {
584
1067
  message: 'Unable to parse the created user from the register service response'
585
1068
  }
@@ -597,18 +1080,18 @@ function* registerSaga({
597
1080
  error.status = response.status;
598
1081
  }
599
1082
  yield effects.put({
600
- type: selectors.REGISTER_USER_FAILED,
1083
+ type: selectors$1.REGISTER_USER_FAILED,
601
1084
  error
602
1085
  });
603
1086
  }
604
1087
  }
605
1088
  function* redirectSaga() {
606
1089
  // Check if querystring contains a redirect_uri
607
- const currentQs = selectors.queryParams(yield effects.select(selectors.selectCurrentSearch));
1090
+ const currentQs = selectors$1.queryParams(yield effects.select(selectors$1.selectCurrentSearch));
608
1091
  const redirectUri = currentQs.redirect_uri || currentQs.redirect;
609
1092
 
610
1093
  // We must use redux based navigation to preserve the registration state
611
- if (redirectUri) yield effects.put(selectors.setRoute(redirectUri));
1094
+ if (redirectUri) yield effects.put(selectors$1.setRoute(redirectUri));
612
1095
  }
613
1096
 
614
1097
  const PAP_URL = 'https://pap.zengenti.com';
@@ -676,11 +1159,11 @@ async function api(url, options) {
676
1159
  });
677
1160
  }
678
1161
 
679
- const resetPasswordSagas = [effects.takeEvery(selectors.REQUEST_USER_PASSWORD_RESET, requestPasswordResetSaga), effects.takeEvery(selectors.RESET_USER_PASSWORD, resetPasswordSaga), effects.takeEvery(selectors.CHANGE_USER_PASSWORD, changePasswordSaga)];
1162
+ const resetPasswordSagas = [effects.takeEvery(selectors$1.REQUEST_USER_PASSWORD_RESET, requestPasswordResetSaga), effects.takeEvery(selectors$1.RESET_USER_PASSWORD, resetPasswordSaga), effects.takeEvery(selectors$1.CHANGE_USER_PASSWORD, changePasswordSaga)];
680
1163
  function* requestPasswordResetSaga(action) {
681
1164
  const userEmailObject = action.userEmailObject;
682
1165
  yield effects.put({
683
- type: selectors.REQUEST_USER_PASSWORD_RESET_SENDING
1166
+ type: selectors$1.REQUEST_USER_PASSWORD_RESET_SENDING
684
1167
  });
685
1168
  if (userEmailObject && userEmailObject.userEmail) {
686
1169
  try {
@@ -688,29 +1171,29 @@ function* requestPasswordResetSaga(action) {
688
1171
  if (passwordResetRequestResponse) {
689
1172
  if (!passwordResetRequestResponse.error) {
690
1173
  yield effects.put({
691
- type: selectors.REQUEST_USER_PASSWORD_RESET_SUCCESS
1174
+ type: selectors$1.REQUEST_USER_PASSWORD_RESET_SUCCESS
692
1175
  });
693
1176
  } else {
694
1177
  yield effects.put({
695
- type: selectors.REQUEST_USER_PASSWORD_RESET_ERROR,
1178
+ type: selectors$1.REQUEST_USER_PASSWORD_RESET_ERROR,
696
1179
  error: passwordResetRequestResponse.error.message
697
1180
  });
698
1181
  }
699
1182
  } else {
700
1183
  yield effects.put({
701
- type: selectors.REQUEST_USER_PASSWORD_RESET_ERROR,
1184
+ type: selectors$1.REQUEST_USER_PASSWORD_RESET_ERROR,
702
1185
  error: 'No response from server'
703
1186
  });
704
1187
  }
705
1188
  } catch (error) {
706
1189
  yield effects.put({
707
- type: selectors.REQUEST_USER_PASSWORD_RESET_ERROR,
1190
+ type: selectors$1.REQUEST_USER_PASSWORD_RESET_ERROR,
708
1191
  error: error && error.toString()
709
1192
  });
710
1193
  }
711
1194
  } else {
712
1195
  yield effects.put({
713
- type: selectors.REQUEST_USER_PASSWORD_RESET_ERROR,
1196
+ type: selectors$1.REQUEST_USER_PASSWORD_RESET_ERROR,
714
1197
  error: 'Invalid object'
715
1198
  });
716
1199
  }
@@ -718,7 +1201,7 @@ function* requestPasswordResetSaga(action) {
718
1201
  function* resetPasswordSaga(action) {
719
1202
  const resetPasswordObject = action.resetPasswordObject;
720
1203
  yield effects.put({
721
- type: selectors.RESET_USER_PASSWORD_SENDING
1204
+ type: selectors$1.RESET_USER_PASSWORD_SENDING
722
1205
  });
723
1206
  if (resetPasswordObject.token && resetPasswordObject.password) {
724
1207
  try {
@@ -726,30 +1209,30 @@ function* resetPasswordSaga(action) {
726
1209
  if (resetPasswordResponse) {
727
1210
  if (!resetPasswordResponse.error) {
728
1211
  yield effects.put({
729
- type: selectors.RESET_USER_PASSWORD_SUCCESS
1212
+ type: selectors$1.RESET_USER_PASSWORD_SUCCESS
730
1213
  });
731
1214
  } else {
732
1215
  const error = resetPasswordResponse.error.data && resetPasswordResponse.error.data.length > 0 && resetPasswordResponse.error.data[0].message || resetPasswordResponse.error.message;
733
1216
  yield effects.put({
734
- type: selectors.RESET_USER_PASSWORD_ERROR,
1217
+ type: selectors$1.RESET_USER_PASSWORD_ERROR,
735
1218
  error
736
1219
  });
737
1220
  }
738
1221
  } else {
739
1222
  yield effects.put({
740
- type: selectors.RESET_USER_PASSWORD_ERROR,
1223
+ type: selectors$1.RESET_USER_PASSWORD_ERROR,
741
1224
  error: 'No response from server'
742
1225
  });
743
1226
  }
744
1227
  } catch (error) {
745
1228
  yield effects.put({
746
- type: selectors.RESET_USER_PASSWORD_ERROR,
1229
+ type: selectors$1.RESET_USER_PASSWORD_ERROR,
747
1230
  error: error && error.toString()
748
1231
  });
749
1232
  }
750
1233
  } else {
751
1234
  yield effects.put({
752
- type: selectors.RESET_USER_PASSWORD_ERROR,
1235
+ type: selectors$1.RESET_USER_PASSWORD_ERROR,
753
1236
  error: 'Invalid object'
754
1237
  });
755
1238
  }
@@ -761,7 +1244,7 @@ function* resetPasswordSaga(action) {
761
1244
  function* changePasswordSaga(action) {
762
1245
  if (!action || !action.userId || !action.currentPassword || !action.newPassword) {
763
1246
  yield effects.put({
764
- type: selectors.CHANGE_USER_PASSWORD_ERROR,
1247
+ type: selectors$1.CHANGE_USER_PASSWORD_ERROR,
765
1248
  error: 'Invalid action object sent to changePassword saga'
766
1249
  });
767
1250
  return;
@@ -773,9 +1256,9 @@ function* changePasswordSaga(action) {
773
1256
  new: action.newPassword
774
1257
  };
775
1258
  yield effects.put({
776
- type: selectors.CHANGE_USER_PASSWORD_SENDING
1259
+ type: selectors$1.CHANGE_USER_PASSWORD_SENDING
777
1260
  });
778
- const clientCredentials = yield effects.select(ToJs.selectClientCredentials, 'js');
1261
+ const clientCredentials = yield effects.select(matchGroups.selectClientCredentials, 'js');
779
1262
  const client = yield ChangePassword_container.getManagementApiClient({
780
1263
  ...clientCredentials
781
1264
  });
@@ -784,22 +1267,17 @@ function* changePasswordSaga(action) {
784
1267
  var _err$data, _err$data2;
785
1268
  const error = (err === null || err === void 0 || (_err$data = err.data) === null || _err$data === void 0 || (_err$data = _err$data.data) === null || _err$data === void 0 ? void 0 : _err$data.length) > 0 && err.data.data[0].message || (err === null || err === void 0 || (_err$data2 = err.data) === null || _err$data2 === void 0 ? void 0 : _err$data2.message);
786
1269
  yield effects.put({
787
- type: selectors.CHANGE_USER_PASSWORD_ERROR,
1270
+ type: selectors$1.CHANGE_USER_PASSWORD_ERROR,
788
1271
  error
789
1272
  });
790
1273
  return;
791
1274
  }
792
-
793
- // // eslint-disable-next-line no-console
794
- // console.log(changePasswordObject);
795
- // // eslint-disable-next-line no-console
796
- // console.log(userCredentialsObject);
797
1275
  yield effects.put({
798
- type: selectors.CHANGE_USER_PASSWORD_SUCCESS
1276
+ type: selectors$1.CHANGE_USER_PASSWORD_SUCCESS
799
1277
  });
800
1278
  } catch (error) {
801
1279
  yield effects.put({
802
- type: selectors.CHANGE_USER_PASSWORD_ERROR,
1280
+ type: selectors$1.CHANGE_USER_PASSWORD_ERROR,
803
1281
  error: error && error.toString()
804
1282
  });
805
1283
  }
@@ -807,13 +1285,16 @@ function* changePasswordSaga(action) {
807
1285
 
808
1286
  const userSagas = [...ChangePassword_container.loginSagas, ...registerSagas, ...resetPasswordSagas];
809
1287
 
810
- // index.js
811
- function rootSaga (featureSagas = []) {
812
- return function* rootSaga() {
813
- const subSagas = [...routingSagas, ...navigationSagas, ...userSagas];
814
- yield effects.all([...subSagas, ...featureSagas]);
815
- };
816
- }
1288
+ var rootSaga = (featureSagas = []) => {
1289
+ return [...i18nSagas, ...routingSagas, ...navigationSagas, ...userSagas, ...featureSagas];
1290
+ };
1291
+
1292
+ // export default function (featureSagas: Effect[] = []) {
1293
+ // return function* rootSaga() {
1294
+ // const subSagas = [...routingSagas, ...navigationSagas, ...userSagas];
1295
+ // yield all([...subSagas, ...featureSagas]);
1296
+ // };
1297
+ // }
817
1298
 
818
1299
  const servers = SERVERS; /* global SERVERS */
819
1300
  const alias = servers.alias.toLowerCase();
@@ -860,7 +1341,9 @@ const AppRoot = props => {
860
1341
 
861
1342
  exports.AppRoot = AppRoot;
862
1343
  exports.browserHistory = browserHistory;
1344
+ exports.createLocaleRoutes = createLocaleRoutes;
863
1345
  exports.history = history;
864
1346
  exports.pickProject = pickProject;
865
1347
  exports.rootSaga = rootSaga;
866
- //# sourceMappingURL=App-vZrUfVgQ.js.map
1348
+ exports.shorten = shorten;
1349
+ //# sourceMappingURL=App-Bg1MzW4V.js.map