@plone/volto 17.0.0-alpha.26 → 17.0.0-alpha.28
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.
- package/.eslintrc +26 -3
- package/.yarn/install-state.gz +0 -0
- package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +541 -0
- package/.yarn/releases/yarn-3.6.3.cjs +874 -0
- package/CHANGELOG.md +60 -0
- package/addon-registry.js +10 -1
- package/create-addons-loader.js +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +57 -31
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +58 -32
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +57 -31
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +65 -39
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +57 -31
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +57 -31
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +57 -31
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +57 -31
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +57 -31
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +57 -31
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +57 -31
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +57 -31
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +57 -31
- package/locales/ro.json +1 -1
- package/locales/volto.pot +62 -32
- package/locales/zh_CN/LC_MESSAGES/volto.po +57 -31
- package/locales/zh_CN.json +1 -1
- package/package.json +35 -26
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +2 -1
- package/packages/volto-slate/src/blocks/Text/index.js +0 -5
- package/packages/volto-slate/src/editor/plugins/Link/render.jsx +5 -6
- package/packages/volto-slate/src/editor/render.jsx +11 -1
- package/razzle.config.js +4 -6
- package/src/components/index.js +194 -194
- package/src/components/manage/Add/Add.jsx +7 -8
- package/src/components/manage/Blocks/Block/Settings.test.jsx +17 -15
- package/src/components/manage/Blocks/HTML/Edit.jsx +8 -8
- package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +30 -25
- package/src/components/manage/Blocks/Listing/ListingBody.jsx +6 -4
- package/src/components/manage/Blocks/Maps/Edit.test.jsx +1 -2
- package/src/components/manage/Blocks/Maps/View.test.jsx +1 -2
- package/src/components/manage/Blocks/Search/components/Facets.jsx +2 -3
- package/src/components/manage/Blocks/Search/components/FilterList.jsx +4 -6
- package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +2 -9
- package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +3 -0
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +8 -6
- package/src/components/manage/Blocks/Search/schema.js +13 -13
- package/src/components/manage/Blocks/Table/Cell.jsx +2 -3
- package/src/components/manage/Blocks/Text/Edit.jsx +2 -3
- package/src/components/manage/Blocks/Title/View.jsx +4 -37
- package/src/components/manage/Blocks/ToC/View.jsx +1 -0
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +3 -2
- package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +3 -2
- package/src/components/manage/Contents/Contents.jsx +252 -114
- package/src/components/manage/Contents/ContentsPropertiesModal.jsx +90 -154
- package/src/components/manage/Contents/ContentsRenameModal.jsx +88 -139
- package/src/components/manage/Contents/ContentsRenameModal.stories.jsx +61 -0
- package/src/components/manage/Contents/ContentsTagsModal.jsx +83 -130
- package/src/components/manage/Contents/ContentsTagsModal.stories.jsx +68 -0
- package/src/components/manage/Contents/ContentsUploadModal.jsx +1 -2
- package/src/components/manage/Contents/ContentsWorkflowModal.jsx +87 -154
- package/src/components/manage/Controlpanels/Aliases.jsx +4 -12
- package/src/components/manage/Controlpanels/Rules/AddRule.jsx +2 -9
- package/src/components/manage/Controlpanels/UndoControlpanel.jsx +6 -9
- package/src/components/manage/Form/BlockDataForm.test.jsx +17 -15
- package/src/components/manage/Form/Form.jsx +2 -3
- package/src/components/manage/Form/InlineForm.test.jsx +16 -14
- package/src/components/manage/LockingToastsFactory/LockingToastsFactory.jsx +1 -2
- package/src/components/manage/Sharing/Sharing.jsx +7 -0
- package/src/components/manage/Sidebar/Sidebar.jsx +139 -220
- package/src/components/manage/Toolbar/More.jsx +12 -12
- package/src/components/manage/Toolbar/PersonalTools.jsx +97 -155
- package/src/components/manage/Toolbar/Toolbar.jsx +2 -2
- package/src/components/manage/UniversalLink/UniversalLink.test.jsx +2 -1
- package/src/components/manage/Widgets/AlignWidget.jsx +2 -4
- package/src/components/manage/Widgets/ColorPickerWidget.test.jsx +9 -7
- package/src/components/manage/Widgets/DatetimeWidget.jsx +2 -8
- package/src/components/manage/Widgets/IdWidget.jsx +1 -2
- package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +2 -9
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +2 -9
- package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +4 -4
- package/src/components/manage/Widgets/SchemaWidget.jsx +6 -9
- package/src/components/manage/Widgets/WysiwygWidget.jsx +2 -9
- package/src/components/theme/Comments/Comments.jsx +3 -10
- package/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +4 -0
- package/src/components/theme/Login/Login.jsx +1 -2
- package/src/components/theme/PasswordReset/PasswordReset.jsx +1 -2
- package/src/components/theme/PreviewImage/PreviewImage.jsx +10 -5
- package/src/components/theme/PreviewImage/PreviewImage.test.js +17 -0
- package/src/components/theme/Register/Register.jsx +2 -4
- package/src/components/theme/TsTest/TsTest.test.tsx +11 -0
- package/src/components/theme/TsTest/TsTest.tsx +15 -0
- package/src/components/theme/View/AlbumView.jsx +3 -2
- package/src/components/theme/Widgets/ImageWidget.stories.jsx +1 -2
- package/src/config/Loadables.jsx +1 -1
- package/src/config/RichTextEditor/Blocks.jsx +2 -3
- package/src/config/RichTextEditor/Plugins.jsx +2 -3
- package/src/config/RichTextEditor/ToHTML.jsx +12 -10
- package/src/config/RichTextEditor/index.js +2 -3
- package/src/config/Views.jsx +5 -5
- package/src/express-middleware/ok.js +1 -1
- package/src/helpers/Blocks/Blocks.js +4 -6
- package/src/helpers/Blocks/Blocks.test.js +35 -35
- package/src/helpers/Extensions/withBlockSchemaEnhancer.js +48 -50
- package/src/helpers/FormValidation/FormValidation.js +7 -6
- package/src/helpers/Html/Html.jsx +2 -8
- package/src/helpers/Loadable/__mocks__/Loadable.js +18 -18
- package/src/helpers/MessageLabels/MessageLabels.js +2 -3
- package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +2 -3
- package/src/helpers/Utils/Utils.js +10 -0
- package/src/helpers/Utils/Utils.test.js +13 -0
- package/src/helpers/index.js +1 -0
- package/src/hooks/index.js +1 -1
- package/src/middleware/api.js +194 -190
- package/src/middleware/blacklistRoutes.js +25 -22
- package/src/middleware/storeProtectLoadUtils.js +61 -62
- package/src/middleware/storeProtectLoadUtils.test.js +47 -43
- package/src/reducers/content/content.test.js +4 -4
- package/src/reducers/navigation/navigation.js +5 -5
- package/src/reducers/navigation/navigation.test.js +30 -0
- package/src/registry.js +2 -2
- package/src/storybook.jsx +24 -38
- package/theme/themes/pastanaga/collections/menu.overrides +3 -2
- package/theme/themes/pastanaga/elements/container.overrides +5 -2
- package/theme/themes/pastanaga/elements/input.overrides +1 -1
- package/theme/themes/pastanaga/elements/step.overrides +2 -1
- package/theme/themes/pastanaga/extras/blocks.less +20 -14
- package/theme/themes/pastanaga/extras/color-picker-widget.less +1 -1
- package/theme/themes/pastanaga/extras/contents.less +5 -1
- package/theme/themes/pastanaga/extras/draftjs.less +4 -4
- package/theme/themes/pastanaga/extras/grid.less +5 -4
- package/theme/themes/pastanaga/extras/main.less +6 -6
- package/theme/themes/pastanaga/extras/react-dates-overrides.less +4 -2
- package/theme/themes/pastanaga/extras/search.less +2 -2
- package/theme/themes/pastanaga/extras/sidebar.less +5 -4
- package/theme/themes/pastanaga/extras/time-picker-overrides.less +5 -3
- package/theme/themes/pastanaga/extras/toolbar.less +6 -2
- package/theme/themes/pastanaga/extras/userscontrolpanel.less +17 -9
- package/theme/themes/pastanaga/extras/widgets.less +1 -1
- package/theme/themes/pastanaga/modules/rating.overrides +2 -1
- package/theme/themes/pastanaga-cms-ui/elements/container.overrides +2 -1
- package/theme/themes/pastanaga-cms-ui/extras/cms-ui.elements.container.less +6 -2
- package/theme/themes/pastanaga-cms-ui/extras/cms-ui.site.less +2 -2
- package/tsconfig.json +33 -0
package/src/middleware/api.js
CHANGED
|
@@ -125,58 +125,76 @@ function sendOnSocket(request) {
|
|
|
125
125
|
* @param {Object} api Api object.
|
|
126
126
|
* @returns {Promise} Action promise.
|
|
127
127
|
*/
|
|
128
|
-
const apiMiddlewareFactory =
|
|
129
|
-
|
|
130
|
-
) =>
|
|
131
|
-
|
|
128
|
+
const apiMiddlewareFactory =
|
|
129
|
+
(api) =>
|
|
130
|
+
({ dispatch, getState }) =>
|
|
131
|
+
(next) =>
|
|
132
|
+
(action) => {
|
|
133
|
+
const { settings } = config;
|
|
132
134
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
const token = getState().userSession.token;
|
|
136
|
+
let isAnonymous = true;
|
|
137
|
+
if (token) {
|
|
138
|
+
const tokenExpiration = jwtDecode(token).exp;
|
|
139
|
+
const currentTime = new Date().getTime() / 1000;
|
|
140
|
+
isAnonymous = !token || currentTime > tokenExpiration;
|
|
141
|
+
}
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
if (typeof action === 'function') {
|
|
144
|
+
return action(dispatch, getState);
|
|
145
|
+
}
|
|
144
146
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
const { request, type, mode = 'parallel', ...rest } = action;
|
|
148
|
+
const { subrequest } = action; // We want subrequest remains in `...rest` above
|
|
147
149
|
|
|
148
|
-
|
|
150
|
+
let actionPromise;
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
if (!request) {
|
|
153
|
+
return next(action);
|
|
154
|
+
}
|
|
153
155
|
|
|
154
|
-
|
|
156
|
+
next({ ...rest, type: `${type}_PENDING` });
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
158
|
+
if (socket) {
|
|
159
|
+
actionPromise = Array.isArray(request)
|
|
160
|
+
? Promise.all(
|
|
161
|
+
request.map((item) =>
|
|
162
|
+
sendOnSocket({
|
|
163
|
+
...item,
|
|
164
|
+
path: addExpandersToPath(item.path, type, isAnonymous),
|
|
165
|
+
id: type,
|
|
166
|
+
}),
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
: sendOnSocket({
|
|
170
|
+
...request,
|
|
171
|
+
path: addExpandersToPath(request.path, type, isAnonymous),
|
|
172
|
+
id: type,
|
|
173
|
+
});
|
|
174
|
+
} else {
|
|
175
|
+
actionPromise = Array.isArray(request)
|
|
176
|
+
? mode === 'serial'
|
|
177
|
+
? request.reduce((prevPromise, item) => {
|
|
178
|
+
return prevPromise.then((acc) => {
|
|
179
|
+
return api[item.op](
|
|
180
|
+
addExpandersToPath(item.path, type, isAnonymous),
|
|
181
|
+
{
|
|
182
|
+
data: item.data,
|
|
183
|
+
type: item.type,
|
|
184
|
+
headers: item.headers,
|
|
185
|
+
params: request.params,
|
|
186
|
+
checkUrl: settings.actions_raising_api_errors.includes(
|
|
187
|
+
action.type,
|
|
188
|
+
),
|
|
189
|
+
},
|
|
190
|
+
).then((reqres) => {
|
|
191
|
+
return [...acc, reqres];
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}, Promise.resolve([]))
|
|
195
|
+
: Promise.all(
|
|
196
|
+
request.map((item) =>
|
|
197
|
+
api[item.op](addExpandersToPath(item.path, type, isAnonymous), {
|
|
180
198
|
data: item.data,
|
|
181
199
|
type: item.type,
|
|
182
200
|
headers: item.headers,
|
|
@@ -184,176 +202,162 @@ const apiMiddlewareFactory = (api) => ({ dispatch, getState }) => (next) => (
|
|
|
184
202
|
checkUrl: settings.actions_raising_api_errors.includes(
|
|
185
203
|
action.type,
|
|
186
204
|
),
|
|
187
|
-
},
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
request.
|
|
195
|
-
|
|
196
|
-
data: item.data,
|
|
197
|
-
type: item.type,
|
|
198
|
-
headers: item.headers,
|
|
199
|
-
params: request.params,
|
|
200
|
-
checkUrl: settings.actions_raising_api_errors.includes(
|
|
201
|
-
action.type,
|
|
202
|
-
),
|
|
203
|
-
}),
|
|
204
|
-
),
|
|
205
|
-
)
|
|
206
|
-
: api[request.op](addExpandersToPath(request.path, type, isAnonymous), {
|
|
207
|
-
data: request.data,
|
|
208
|
-
type: request.type,
|
|
209
|
-
headers: request.headers,
|
|
210
|
-
params: request.params,
|
|
211
|
-
checkUrl: settings.actions_raising_api_errors.includes(action.type),
|
|
212
|
-
});
|
|
213
|
-
actionPromise.then(
|
|
214
|
-
(result) => {
|
|
215
|
-
const { settings } = config;
|
|
216
|
-
if (getState().apierror.connectionRefused) {
|
|
217
|
-
next({
|
|
218
|
-
...rest,
|
|
219
|
-
type: RESET_APIERROR,
|
|
205
|
+
}),
|
|
206
|
+
),
|
|
207
|
+
)
|
|
208
|
+
: api[request.op](addExpandersToPath(request.path, type, isAnonymous), {
|
|
209
|
+
data: request.data,
|
|
210
|
+
type: request.type,
|
|
211
|
+
headers: request.headers,
|
|
212
|
+
params: request.params,
|
|
213
|
+
checkUrl: settings.actions_raising_api_errors.includes(action.type),
|
|
220
214
|
});
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
config.settings.supportedLanguages.includes(lang)
|
|
229
|
-
) {
|
|
230
|
-
const langFileName = toGettextLang(lang);
|
|
231
|
-
import('~/../locales/' + langFileName + '.json').then((locale) => {
|
|
232
|
-
dispatch(changeLanguage(lang, locale.default));
|
|
215
|
+
actionPromise.then(
|
|
216
|
+
(result) => {
|
|
217
|
+
const { settings } = config;
|
|
218
|
+
if (getState().apierror.connectionRefused) {
|
|
219
|
+
next({
|
|
220
|
+
...rest,
|
|
221
|
+
type: RESET_APIERROR,
|
|
233
222
|
});
|
|
234
223
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
224
|
+
if (type === GET_CONTENT) {
|
|
225
|
+
const lang = result?.language?.token;
|
|
226
|
+
if (
|
|
227
|
+
lang &&
|
|
228
|
+
getState().intl.locale !== toReactIntlLang(lang) &&
|
|
229
|
+
!subrequest &&
|
|
230
|
+
config.settings.supportedLanguages.includes(lang)
|
|
231
|
+
) {
|
|
232
|
+
const langFileName = toGettextLang(lang);
|
|
233
|
+
import('~/../locales/' + langFileName + '.json').then(
|
|
234
|
+
(locale) => {
|
|
235
|
+
dispatch(changeLanguage(lang, locale.default));
|
|
236
|
+
},
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (type === LOGIN && settings.websockets) {
|
|
241
|
+
const cookies = new Cookies();
|
|
242
|
+
cookies.set(
|
|
243
|
+
'auth_token',
|
|
244
|
+
result.token,
|
|
245
|
+
getCookieOptions({
|
|
246
|
+
expires: new Date(jwtDecode(result.token).exp * 1000),
|
|
247
|
+
}),
|
|
250
248
|
);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
next({
|
|
272
|
-
...rest,
|
|
273
|
-
error: { status: 500, error },
|
|
274
|
-
type: `${type}_FAIL`,
|
|
275
|
-
});
|
|
276
|
-
// Rethrow the original exception on the client side only,
|
|
277
|
-
// so it doesn't fall through to express on the server.
|
|
278
|
-
if (__CLIENT__) throw error;
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
(error) => {
|
|
282
|
-
// Only SSR can set ECONNREFUSED
|
|
283
|
-
if (error.code === 'ECONNREFUSED') {
|
|
284
|
-
next({
|
|
285
|
-
...rest,
|
|
286
|
-
error,
|
|
287
|
-
statusCode: error.code,
|
|
288
|
-
connectionRefused: true,
|
|
289
|
-
type: SET_APIERROR,
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Response error is marked crossDomain if CORS error happen
|
|
294
|
-
else if (error.crossDomain) {
|
|
295
|
-
next({
|
|
296
|
-
...rest,
|
|
297
|
-
error,
|
|
298
|
-
statusCode: 'CORSERROR',
|
|
299
|
-
connectionRefused: false,
|
|
300
|
-
type: SET_APIERROR,
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Check for actions who can raise api errors
|
|
305
|
-
if (settings.actions_raising_api_errors.includes(action.type)) {
|
|
306
|
-
// Gateway timeout
|
|
307
|
-
if (error?.response?.statusCode === 504) {
|
|
308
|
-
next({
|
|
309
|
-
...rest,
|
|
310
|
-
error,
|
|
311
|
-
statusCode: error.code,
|
|
312
|
-
connectionRefused: true,
|
|
313
|
-
type: SET_APIERROR,
|
|
249
|
+
api.get('/@wstoken').then((res) => {
|
|
250
|
+
socket = new WebSocket(
|
|
251
|
+
`${settings.apiPath.replace('http', 'ws')}/@ws?ws_token=${
|
|
252
|
+
res.token
|
|
253
|
+
}`,
|
|
254
|
+
);
|
|
255
|
+
socket.onmessage = (message) => {
|
|
256
|
+
const packet = JSON.parse(message.data);
|
|
257
|
+
if (packet.error) {
|
|
258
|
+
dispatch({
|
|
259
|
+
type: `${packet.id}_FAIL`,
|
|
260
|
+
error: packet.error,
|
|
261
|
+
});
|
|
262
|
+
} else {
|
|
263
|
+
dispatch({
|
|
264
|
+
type: `${packet.id}_SUCCESS`,
|
|
265
|
+
result: JSON.parse(packet.data),
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
};
|
|
314
269
|
});
|
|
315
270
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
271
|
+
try {
|
|
272
|
+
return next({ ...rest, result, type: `${type}_SUCCESS` });
|
|
273
|
+
} catch (error) {
|
|
274
|
+
// There was an exception while processing reducers or downstream middleware.
|
|
319
275
|
next({
|
|
320
276
|
...rest,
|
|
321
|
-
error,
|
|
322
|
-
|
|
323
|
-
connectionRefused: false,
|
|
324
|
-
type: SET_APIERROR,
|
|
277
|
+
error: { status: 500, error },
|
|
278
|
+
type: `${type}_FAIL`,
|
|
325
279
|
});
|
|
280
|
+
// Rethrow the original exception on the client side only,
|
|
281
|
+
// so it doesn't fall through to express on the server.
|
|
282
|
+
if (__CLIENT__) throw error;
|
|
326
283
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
284
|
+
},
|
|
285
|
+
(error) => {
|
|
286
|
+
// Only SSR can set ECONNREFUSED
|
|
287
|
+
if (error.code === 'ECONNREFUSED') {
|
|
330
288
|
next({
|
|
331
289
|
...rest,
|
|
332
290
|
error,
|
|
333
291
|
statusCode: error.code,
|
|
334
|
-
connectionRefused:
|
|
292
|
+
connectionRefused: true,
|
|
335
293
|
type: SET_APIERROR,
|
|
336
294
|
});
|
|
337
295
|
}
|
|
338
296
|
|
|
339
|
-
//
|
|
340
|
-
else if (error
|
|
297
|
+
// Response error is marked crossDomain if CORS error happen
|
|
298
|
+
else if (error.crossDomain) {
|
|
341
299
|
next({
|
|
342
300
|
...rest,
|
|
343
301
|
error,
|
|
344
|
-
statusCode:
|
|
345
|
-
message: error.response.body.message,
|
|
302
|
+
statusCode: 'CORSERROR',
|
|
346
303
|
connectionRefused: false,
|
|
347
304
|
type: SET_APIERROR,
|
|
348
305
|
});
|
|
349
306
|
}
|
|
350
|
-
}
|
|
351
|
-
return next({ ...rest, error, type: `${type}_FAIL` });
|
|
352
|
-
},
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
307
|
|
|
356
|
-
|
|
357
|
-
|
|
308
|
+
// Check for actions who can raise api errors
|
|
309
|
+
if (settings.actions_raising_api_errors.includes(action.type)) {
|
|
310
|
+
// Gateway timeout
|
|
311
|
+
if (error?.response?.statusCode === 504) {
|
|
312
|
+
next({
|
|
313
|
+
...rest,
|
|
314
|
+
error,
|
|
315
|
+
statusCode: error.code,
|
|
316
|
+
connectionRefused: true,
|
|
317
|
+
type: SET_APIERROR,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Redirect
|
|
322
|
+
else if (error?.code === 301) {
|
|
323
|
+
next({
|
|
324
|
+
...rest,
|
|
325
|
+
error,
|
|
326
|
+
statusCode: error.code,
|
|
327
|
+
connectionRefused: false,
|
|
328
|
+
type: SET_APIERROR,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Redirect
|
|
333
|
+
else if (error?.code === 408) {
|
|
334
|
+
next({
|
|
335
|
+
...rest,
|
|
336
|
+
error,
|
|
337
|
+
statusCode: error.code,
|
|
338
|
+
connectionRefused: false,
|
|
339
|
+
type: SET_APIERROR,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Unauthorized
|
|
344
|
+
else if (error?.response?.statusCode === 401) {
|
|
345
|
+
next({
|
|
346
|
+
...rest,
|
|
347
|
+
error,
|
|
348
|
+
statusCode: error.response,
|
|
349
|
+
message: error.response.body.message,
|
|
350
|
+
connectionRefused: false,
|
|
351
|
+
type: SET_APIERROR,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return next({ ...rest, error, type: `${type}_FAIL` });
|
|
356
|
+
},
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return actionPromise;
|
|
361
|
+
};
|
|
358
362
|
|
|
359
363
|
export default apiMiddlewareFactory;
|
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
import config from '@plone/volto/registry';
|
|
2
2
|
import { matchPath } from 'react-router';
|
|
3
3
|
|
|
4
|
-
const blacklistRoutes =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const blacklistRoutes =
|
|
5
|
+
({ dispatch, getState }) =>
|
|
6
|
+
(next) =>
|
|
7
|
+
(action) => {
|
|
8
|
+
if (typeof action === 'function') {
|
|
9
|
+
return next(action);
|
|
10
|
+
}
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
switch (action.type) {
|
|
13
|
+
case '@@router/LOCATION_CHANGE':
|
|
14
|
+
const { pathname } = action.payload.location;
|
|
15
|
+
const { externalRoutes = [] } = config.settings;
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
const route = externalRoutes.find((route) =>
|
|
18
|
+
matchPath(pathname, route.match),
|
|
19
|
+
);
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
if (!route) {
|
|
22
|
+
return next(action);
|
|
23
|
+
} else {
|
|
24
|
+
window.location.replace(
|
|
25
|
+
route.url ? route.url(action.payload) : pathname,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
19
30
|
return next(action);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
route.url ? route.url(action.payload) : pathname,
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
break;
|
|
26
|
-
default:
|
|
27
|
-
return next(action);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
30
33
|
|
|
31
34
|
export default blacklistRoutes;
|
|
@@ -21,42 +21,43 @@ const RESET_CONTENT = 'RESET_CONTENT';
|
|
|
21
21
|
// such a reset when navigating between two content routes.
|
|
22
22
|
// ---
|
|
23
23
|
|
|
24
|
-
export const protectLoadStart =
|
|
25
|
-
|
|
26
|
-
) =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
switch (action.type) {
|
|
31
|
-
case LOCATION_CHANGE:
|
|
32
|
-
const { location } = action.payload;
|
|
33
|
-
const { pathname: path } = location;
|
|
34
|
-
const currentPath = getState().router.location.pathname;
|
|
35
|
-
const result = next(action);
|
|
36
|
-
if (isCmsUi(path)) {
|
|
37
|
-
// Next path: isCmsUI, Non Content. There is no
|
|
38
|
-
// loading here, so skip counting altogether.
|
|
39
|
-
// Will update the delayed location constantly.
|
|
40
|
-
dispatch({
|
|
41
|
-
type: PROTECT_SKIPPED,
|
|
42
|
-
location,
|
|
43
|
-
});
|
|
44
|
-
} else {
|
|
45
|
-
dispatch({
|
|
46
|
-
type: PROTECT_START,
|
|
47
|
-
location,
|
|
48
|
-
// Only reset before the fetch, if we depart from
|
|
49
|
-
// a not isCmsUi, Content pass. However, reset will
|
|
50
|
-
// not occur if moving between two content paths,
|
|
51
|
-
// only the postponed location will be booked.
|
|
52
|
-
resetBeforeFetch: isCmsUi(currentPath),
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return result;
|
|
56
|
-
default:
|
|
24
|
+
export const protectLoadStart =
|
|
25
|
+
({ dispatch, getState }) =>
|
|
26
|
+
(next) =>
|
|
27
|
+
(action) => {
|
|
28
|
+
if (typeof action === 'function') {
|
|
57
29
|
return next(action);
|
|
58
|
-
|
|
59
|
-
|
|
30
|
+
}
|
|
31
|
+
switch (action.type) {
|
|
32
|
+
case LOCATION_CHANGE:
|
|
33
|
+
const { location } = action.payload;
|
|
34
|
+
const { pathname: path } = location;
|
|
35
|
+
const currentPath = getState().router.location.pathname;
|
|
36
|
+
const result = next(action);
|
|
37
|
+
if (isCmsUi(path)) {
|
|
38
|
+
// Next path: isCmsUI, Non Content. There is no
|
|
39
|
+
// loading here, so skip counting altogether.
|
|
40
|
+
// Will update the delayed location constantly.
|
|
41
|
+
dispatch({
|
|
42
|
+
type: PROTECT_SKIPPED,
|
|
43
|
+
location,
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
dispatch({
|
|
47
|
+
type: PROTECT_START,
|
|
48
|
+
location,
|
|
49
|
+
// Only reset before the fetch, if we depart from
|
|
50
|
+
// a not isCmsUi, Content pass. However, reset will
|
|
51
|
+
// not occur if moving between two content paths,
|
|
52
|
+
// only the postponed location will be booked.
|
|
53
|
+
resetBeforeFetch: isCmsUi(currentPath),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
default:
|
|
58
|
+
return next(action);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
60
61
|
|
|
61
62
|
// Note that there is a bit of heuristics here. We assume that every action
|
|
62
63
|
// like this is beginning/ending an action. If this logic fails then the counting
|
|
@@ -70,34 +71,32 @@ const mapActions = {
|
|
|
70
71
|
[GET_CONTENT_PENDING]: RESET_CONTENT,
|
|
71
72
|
};
|
|
72
73
|
|
|
73
|
-
export const protectLoadEnd =
|
|
74
|
-
|
|
75
|
-
) =>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const {
|
|
80
|
-
isCounting,
|
|
81
|
-
resetBeforeFetch,
|
|
82
|
-
requestCount,
|
|
83
|
-
} = getState().loadProtector;
|
|
84
|
-
if (resetBeforeFetch) {
|
|
85
|
-
const type = mapActions[action.type];
|
|
86
|
-
if (type) {
|
|
87
|
-
dispatch({ type });
|
|
74
|
+
export const protectLoadEnd =
|
|
75
|
+
({ dispatch, getState }) =>
|
|
76
|
+
(next) =>
|
|
77
|
+
(action) => {
|
|
78
|
+
if (typeof action === 'function') {
|
|
79
|
+
return next(action);
|
|
88
80
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
const { isCounting, resetBeforeFetch, requestCount } =
|
|
82
|
+
getState().loadProtector;
|
|
83
|
+
if (resetBeforeFetch) {
|
|
84
|
+
const type = mapActions[action.type];
|
|
85
|
+
if (type) {
|
|
86
|
+
dispatch({ type });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (isCounting && requestCount === 1 && isResponseAction(action)) {
|
|
90
|
+
setTimeout(
|
|
91
|
+
() =>
|
|
92
|
+
dispatch({
|
|
93
|
+
type: PROTECT_END,
|
|
94
|
+
}),
|
|
95
|
+
0,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
return next(action);
|
|
99
|
+
};
|
|
101
100
|
|
|
102
101
|
export function loadProtector(state = {}, action = {}) {
|
|
103
102
|
switch (action.type) {
|