@plone/volto 17.0.0-alpha.21 → 17.0.0-alpha.22

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 (70) hide show
  1. package/.gitignore~ +71 -0
  2. package/.yarn/install-state.gz +0 -0
  3. package/CHANGELOG.md +30 -0
  4. package/locales/ca/LC_MESSAGES/volto.po +14 -4
  5. package/locales/ca.json +1 -1
  6. package/locales/de/LC_MESSAGES/volto.po +27 -17
  7. package/locales/de.json +1 -1
  8. package/locales/en/LC_MESSAGES/volto.po +15 -5
  9. package/locales/en.json +1 -1
  10. package/locales/es/LC_MESSAGES/volto.po +15 -5
  11. package/locales/es.json +1 -1
  12. package/locales/eu/LC_MESSAGES/volto.po +14 -4
  13. package/locales/eu.json +1 -1
  14. package/locales/fi/LC_MESSAGES/volto.po +14 -4
  15. package/locales/fi.json +1 -1
  16. package/locales/fr/LC_MESSAGES/volto.po +14 -4
  17. package/locales/fr.json +1 -1
  18. package/locales/it/LC_MESSAGES/volto.po +239 -229
  19. package/locales/it.json +1 -1
  20. package/locales/ja/LC_MESSAGES/volto.po +14 -4
  21. package/locales/ja.json +1 -1
  22. package/locales/nl/LC_MESSAGES/volto.po +14 -4
  23. package/locales/nl.json +1 -1
  24. package/locales/pt/LC_MESSAGES/volto.po +14 -4
  25. package/locales/pt.json +1 -1
  26. package/locales/pt_BR/LC_MESSAGES/volto.po +15 -5
  27. package/locales/pt_BR.json +1 -1
  28. package/locales/ro/LC_MESSAGES/volto.po +14 -4
  29. package/locales/ro.json +1 -1
  30. package/locales/volto.pot +15 -5
  31. package/locales/zh_CN/LC_MESSAGES/volto.po +14 -4
  32. package/locales/zh_CN.json +1 -1
  33. package/news/4547.breaking~ +1 -0
  34. package/package.json +3 -3
  35. package/packages/volto-slate/package.json +1 -1
  36. package/src/actions/relations/rebuild.js +7 -7
  37. package/src/components/manage/Actions/Actions.jsx +133 -243
  38. package/src/components/manage/Blocks/Container/Edit.jsx +4 -1
  39. package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +1 -0
  40. package/src/components/manage/Blocks/Grid/Edit.jsx +13 -1
  41. package/src/components/manage/Blocks/Image/View.jsx +2 -1
  42. package/src/components/manage/Blocks/Maps/Edit.jsx +135 -209
  43. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +3 -2
  44. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +1 -13
  45. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +2 -2
  46. package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +30 -7
  47. package/src/components/manage/Controlpanels/Relations/Relations.jsx +2 -2
  48. package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +53 -59
  49. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +2 -2
  50. package/src/components/manage/Delete/Delete.jsx +96 -171
  51. package/src/components/manage/Widgets/SelectUtils.js +1 -1
  52. package/src/components/manage/Workflow/Workflow.jsx +75 -184
  53. package/src/components/theme/PasswordReset/RequestPasswordReset.jsx +95 -170
  54. package/src/config/Components.jsx +1 -0
  55. package/src/config/index.js~ +223 -0
  56. package/src/express-middleware/files.js +8 -6
  57. package/src/express-middleware/images.js +7 -1
  58. package/src/helpers/MessageLabels/MessageLabels.js +6 -0
  59. package/src/reducers/relations/relations.js +1 -1
  60. package/theme/themes/pastanaga/extras/blocks.less +1 -1
  61. package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +0 -90
  62. package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +0 -6
  63. package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +0 -6
  64. package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +0 -6
  65. package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +0 -10
  66. package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +0 -10
  67. package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +0 -30
  68. package/packages/volto-slate/build/messages/src/elementEditor/messages.json +0 -10
  69. package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +0 -6
  70. package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +0 -6
@@ -1,17 +1,10 @@
1
- /**
2
- * RequestPasswordReset component.
3
- * @module components/theme/RequestPasswordReset/RequestPasswordReset
4
- */
5
-
6
- import React, { Component } from 'react';
7
- import PropTypes from 'prop-types';
8
- import { connect } from 'react-redux';
9
- import { compose } from 'redux';
10
- import { withRouter } from 'react-router-dom';
11
- import { Helmet } from '@plone/volto/helpers';
1
+ import { useState, useEffect, useRef } from 'react';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
+ import { useHistory } from 'react-router-dom';
12
4
  import { Container } from 'semantic-ui-react';
13
- import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
5
+ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
14
6
 
7
+ import { Helmet, usePrevious } from '@plone/volto/helpers';
15
8
  import { Form } from '@plone/volto/components';
16
9
  import { resetPassword } from '@plone/volto/actions';
17
10
  import config from '@plone/volto/registry';
@@ -56,178 +49,110 @@ const messages = defineMessages({
56
49
  },
57
50
  });
58
51
 
59
- /**
60
- * RequestPasswordReset class.
61
- * @class RequestPasswordReset
62
- * @extends Component
63
- */
64
- class RequestPasswordReset extends Component {
65
- /**
66
- * Property types.
67
- * @property {Object} propTypes Property types.
68
- * @static
69
- */
70
- static propTypes = {
71
- loading: PropTypes.bool.isRequired,
72
- loaded: PropTypes.bool.isRequired,
73
- error: PropTypes.string,
74
- resetPassword: PropTypes.func.isRequired,
75
- };
52
+ const useUsers = () => {
53
+ const loading = useSelector((state) => state.users.reset.loading);
54
+ const loaded = useSelector((state) => state.users.reset.loaded);
55
+ const error = useSelector((state) => state.users.reset.error);
76
56
 
77
- /**
78
- * Default properties.
79
- * @property {Object} defaultProps Default properties.
80
- * @static
81
- */
82
- static defaultProps = {
83
- error: null,
84
- };
57
+ return { loading, loaded, error };
58
+ };
85
59
 
86
- /**
87
- * Constructor
88
- * @method constructor
89
- * @param {Object} props Component properties
90
- * @constructs Controlpanel
91
- */
92
- constructor(props) {
93
- super(props);
94
- this.onCancel = this.onCancel.bind(this);
95
- this.onSubmit = this.onSubmit.bind(this);
96
- this.identifierField = config.settings.useEmailAsLogin
97
- ? 'email'
98
- : 'username';
60
+ const RequestPasswordReset = () => {
61
+ const intl = useIntl();
62
+ const dispatch = useDispatch();
63
+ const [error, setError] = useState(null);
64
+ const [isSuccessful, setisSuccessful] = useState(false);
65
+ const history = useHistory();
66
+ const identifierTitle = useRef();
67
+ const identifierRequiredMessage = useRef();
68
+ const { loaded, loading, error: props_error } = useUsers();
69
+ const prevloading = usePrevious(loading);
99
70
 
100
- if (this.identifierField === 'email') {
101
- this.identifierTitle = this.props.intl.formatMessage(messages.emailTitle);
102
- this.identifierRequiredMessage = this.props.intl.formatMessage(
103
- messages.emailRequired,
104
- );
105
- } else {
106
- this.identifierTitle = this.props.intl.formatMessage(
107
- messages.usernameTitle,
108
- );
109
- this.identifierRequiredMessage = this.props.intl.formatMessage(
110
- messages.usernameRequired,
111
- );
112
- }
71
+ const identifierField = config.settings.useEmailAsLogin
72
+ ? 'email'
73
+ : 'username';
113
74
 
114
- this.state = {
115
- error: null,
116
- isSuccessful: false,
117
- };
75
+ if (identifierField === 'email') {
76
+ identifierTitle.current = intl.formatMessage(messages.emailTitle);
77
+ identifierRequiredMessage.current = intl.formatMessage(
78
+ messages.emailRequired,
79
+ );
80
+ } else {
81
+ identifierTitle.current = intl.formatMessage(messages.usernameTitle);
82
+ identifierRequiredMessage.current = intl.formatMessage(
83
+ messages.usernameRequired,
84
+ );
118
85
  }
119
86
 
120
- /**
121
- * Component will receive props
122
- * @method componentWillReceiveProps
123
- * @param {Object} nextProps Next properties
124
- * @returns {undefined}
125
- */
126
- UNSAFE_componentWillReceiveProps(nextProps) {
127
- if (this.props.loading && nextProps.loaded) {
128
- this.setState({ isSuccessful: true });
129
- }
130
- }
87
+ useEffect(() => {
88
+ if (prevloading && loaded) setisSuccessful(true);
89
+ }, [prevloading, loaded]);
131
90
 
132
- /**
133
- * Submit handler
134
- * @method onSubmit
135
- * @param {object} data Form data.
136
- * @param {object} event Form data.
137
- * @returns {undefined}
138
- */
139
- onSubmit(data) {
140
- if (data[this.identifierField]) {
141
- this.props.resetPassword(data[this.identifierField]);
142
- this.setState({
143
- error: null,
144
- });
91
+ const onSubmit = (data) => {
92
+ if (data[identifierField]) {
93
+ dispatch(resetPassword(data[identifierField]));
94
+ setError(null);
145
95
  } else {
146
- this.setState({
147
- error: {
148
- message: this.identifierRequiredMessage,
149
- },
96
+ setError({
97
+ message: identifierRequiredMessage.current,
150
98
  });
151
99
  }
152
- }
153
-
154
- /**
155
- * Cancel handler
156
- * @method onCancel
157
- * @returns {undefined}
158
- */
159
- onCancel() {
160
- this.props.history.goBack();
161
- }
100
+ };
162
101
 
163
- /**
164
- * Render method.
165
- * @method render
166
- * @returns {string} Markup for the component.
167
- */
168
- render() {
169
- if (this.state.isSuccessful) {
170
- return (
171
- <Container>
172
- <h1 className="documentFirstHeading">
173
- <FormattedMessage
174
- id="heading_sent_password"
175
- defaultMessage="Password reset confirmation sent"
176
- />
177
- </h1>
178
- <p className="description">
179
- <FormattedMessage
180
- id="description_sent_password"
181
- defaultMessage="Your password reset request has been mailed. It should arrive in your mailbox shortly. When you receive the message, visit the address it contains to reset your password."
182
- />
183
- </p>
184
- </Container>
185
- );
186
- }
102
+ const onCancel = () => {
103
+ history.goBack();
104
+ };
187
105
 
106
+ if (isSuccessful) {
188
107
  return (
189
- <div id="page-password-reset">
190
- <Helmet title={this.props.intl.formatMessage(messages.passwordReset)} />
191
- <Container>
192
- <Form
193
- title={this.props.intl.formatMessage(messages.title)}
194
- description={this.props.intl.formatMessage(messages.description)}
195
- onSubmit={this.onSubmit}
196
- onCancel={this.onCancel}
197
- error={this.state.error || this.props.error}
198
- schema={{
199
- fieldsets: [
200
- {
201
- id: 'default',
202
- title: this.props.intl.formatMessage(messages.default),
203
- fields: [this.identifierField],
204
- },
205
- ],
206
- properties: {
207
- [this.identifierField]: {
208
- type: 'string',
209
- title: this.identifierTitle,
210
- },
211
- },
212
- submitLabel: this.props.intl.formatMessage(messages.sendEmail),
213
- required: [this.identifierField],
214
- }}
108
+ <Container>
109
+ <h1 className="documentFirstHeading">
110
+ <FormattedMessage
111
+ id="heading_sent_password"
112
+ defaultMessage="Password reset confirmation sent"
113
+ />
114
+ </h1>
115
+ <p className="description">
116
+ <FormattedMessage
117
+ id="description_sent_password"
118
+ defaultMessage="Your password reset request has been mailed. It should arrive in your mailbox shortly. When you receive the message, visit the address it contains to reset your password."
215
119
  />
216
- </Container>
217
- </div>
120
+ </p>
121
+ </Container>
218
122
  );
219
123
  }
220
- }
221
124
 
222
- export default compose(
223
- withRouter,
224
- injectIntl,
225
- connect(
226
- (state) => ({
227
- loading: state.users.reset.loading,
228
- loaded: state.users.reset.loaded,
229
- error: state.users.reset.error,
230
- }),
231
- { resetPassword },
232
- ),
233
- )(RequestPasswordReset);
125
+ return (
126
+ <div id="page-password-reset">
127
+ <Helmet title={intl.formatMessage(messages.passwordReset)} />
128
+ <Container>
129
+ <Form
130
+ title={intl.formatMessage(messages.title)}
131
+ description={intl.formatMessage(messages.description)}
132
+ onSubmit={onSubmit}
133
+ onCancel={onCancel}
134
+ error={error || props_error}
135
+ schema={{
136
+ fieldsets: [
137
+ {
138
+ id: 'default',
139
+ title: intl.formatMessage(messages.default),
140
+ fields: [identifierField],
141
+ },
142
+ ],
143
+ properties: {
144
+ [identifierField]: {
145
+ type: 'string',
146
+ title: identifierTitle.current,
147
+ },
148
+ },
149
+ submitLabel: intl.formatMessage(messages.sendEmail),
150
+ required: [identifierField],
151
+ }}
152
+ />
153
+ </Container>
154
+ </div>
155
+ );
156
+ };
157
+
158
+ export default RequestPasswordReset;
@@ -1,5 +1,6 @@
1
1
  import { App, PreviewImage, Image } from '@plone/volto/components';
2
2
 
3
+ // Register components.
3
4
  export const components = {
4
5
  PreviewImage: { component: PreviewImage },
5
6
  App: { component: App },
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Config.
3
+ * @module config
4
+ */
5
+ import { parse as parseUrl } from 'url';
6
+ import { defaultWidget, widgetMapping } from './Widgets';
7
+ import {
8
+ layoutViews,
9
+ contentTypesViews,
10
+ defaultView,
11
+ errorViews,
12
+ layoutViewsNamesMapping,
13
+ } from './Views';
14
+ import { nonContentRoutes } from './NonContentRoutes';
15
+ import {
16
+ groupBlocksOrder,
17
+ requiredBlocks,
18
+ blocksConfig,
19
+ initialBlocks,
20
+ initialBlocksFocus,
21
+ } from './Blocks';
22
+ import { components } from './Components';
23
+ import { loadables } from './Loadables';
24
+ import { workflowMapping } from './Workflows';
25
+
26
+ import { contentIcons } from './ContentIcons';
27
+ import { styleClassNameConverters, styleClassNameExtenders } from './Style';
28
+ import {
29
+ controlPanelsIcons,
30
+ filterControlPanels,
31
+ filterControlPanelsSchema,
32
+ } from './ControlPanels';
33
+
34
+ import { richtextEditorSettings, richtextViewSettings } from './RichTextEditor';
35
+
36
+ import applyAddonConfiguration, { addonsInfo } from 'load-volto-addons';
37
+
38
+ import ConfigRegistry from '@plone/volto/registry';
39
+
40
+ const host = process.env.HOST || 'localhost';
41
+ const port = process.env.PORT || '3000';
42
+
43
+ const apiPath =
44
+ process.env.RAZZLE_API_PATH ||
45
+ (__DEVELOPMENT__ ? `http://${host}:${port}` : '');
46
+
47
+ const getServerURL = (url) => {
48
+ if (!url) return;
49
+ const apiPathURL = parseUrl(url);
50
+ return `${apiPathURL.protocol}//${apiPathURL.hostname}${
51
+ apiPathURL.port ? `:${apiPathURL.port}` : ''
52
+ }`;
53
+ };
54
+
55
+ // Sensible defaults for publicURL
56
+ // if RAZZLE_PUBLIC_URL is present, use it
57
+ // if in DEV, use the host/port combination by default
58
+ // if in PROD, assume it's RAZZLE_API_PATH server name (no /api or alikes) or fallback
59
+ // to DEV settings if RAZZLE_API_PATH is not present
60
+ const publicURL =
61
+ process.env.RAZZLE_PUBLIC_URL ||
62
+ (__DEVELOPMENT__
63
+ ? `http://${host}:${port}`
64
+ : getServerURL(process.env.RAZZLE_API_PATH) || `http://${host}:${port}`);
65
+
66
+ const serverConfig =
67
+ typeof __SERVER__ !== 'undefined' && __SERVER__
68
+ ? require('./server').default
69
+ : {};
70
+
71
+ let config = {
72
+ settings: {
73
+ host,
74
+ port,
75
+ // The URL Volto is going to be served (see sensible defaults above)
76
+ publicURL,
77
+ apiPath,
78
+ apiExpanders: [
79
+ // Add the following expanders for only issuing a single request.
80
+ // https://6.docs.plone.org/volto/configuration/settings-reference.html#term-apiExpanders
81
+ // {
82
+ // match: '',
83
+ // GET_CONTENT: ['breadcrumbs', 'navigation', 'actions', 'types'],
84
+ // },
85
+ ],
86
+ // Internal proxy to bypass CORS *while developing*. NOT intended for production use.
87
+ // In production is recommended you use a Seamless mode deployment using a web server in
88
+ // front of both the frontend and the backend so you can bypass CORS safely.
89
+ // https://6.docs.plone.org/volto/deploying/seamless-mode.html
90
+ devProxyToApiPath:
91
+ process.env.RAZZLE_DEV_PROXY_API_PATH ||
92
+ process.env.RAZZLE_INTERNAL_API_PATH ||
93
+ process.env.RAZZLE_API_PATH ||
94
+ 'http://localhost:8080/Plone', // Set it to '' for disabling the proxy
95
+ // proxyRewriteTarget Set it for set a custom target for the proxy or overide the internal VHM rewrite
96
+ // proxyRewriteTarget: '/VirtualHostBase/http/localhost:8080/Plone/VirtualHostRoot/_vh_api'
97
+ // proxyRewriteTarget: 'https://myvoltositeinproduction.com'
98
+ proxyRewriteTarget: process.env.RAZZLE_PROXY_REWRITE_TARGET || undefined,
99
+ // apiPath: process.env.RAZZLE_API_PATH || 'http://localhost:8000', // for Volto reference
100
+ // apiPath: process.env.RAZZLE_API_PATH || 'http://localhost:8081/db/web', // for guillotina
101
+ actions_raising_api_errors: ['GET_CONTENT', 'UPDATE_CONTENT'],
102
+ internalApiPath: process.env.RAZZLE_INTERNAL_API_PATH || undefined,
103
+ websockets: process.env.RAZZLE_WEBSOCKETS || false,
104
+ // TODO: legacyTraverse to be removed when the use of the legacy traverse is deprecated.
105
+ legacyTraverse: process.env.RAZZLE_LEGACY_TRAVERSE || false,
106
+ cookieExpires: 15552000, //in seconds. Default is 6 month (15552000)
107
+ nonContentRoutes,
108
+ richtextEditorSettings, // Part of draftjs support, to be removed
109
+ richtextViewSettings, // Part of draftjs support, to be removed
110
+ imageObjects: ['Image'],
111
+ reservedIds: ['login', 'layout', 'plone', 'zip', 'properties'],
112
+ downloadableObjects: ['File'], //list of content-types for which the direct download of the file will be carried out if the user is not authenticated
113
+ viewableInBrowserObjects: [], //ex: ['File']. List of content-types for which the file will be displayed in browser if the user is not authenticated
114
+ listingPreviewImageField: 'image', // deprecated from Volto 14 onwards
115
+ openExternalLinkInNewTab: false,
116
+ notSupportedBrowsers: ['ie'],
117
+ defaultPageSize: 25,
118
+ isMultilingual: false,
119
+ supportedLanguages: ['en'],
120
+ defaultLanguage: 'en',
121
+ navDepth: 1,
122
+ expressMiddleware: serverConfig.expressMiddleware, // BBB
123
+ defaultBlockType: 'slate',
124
+ verticalFormTabs: false,
125
+ useEmailAsLogin: false,
126
+ persistentReducers: ['blocksClipboard'],
127
+ initialReducersBlacklist: [], // reducers in this list won't be hydrated in windows.__data
128
+ asyncPropsExtenders: [], // per route asyncConnect customizers
129
+ contentIcons: contentIcons,
130
+ loadables,
131
+ lazyBundles: {
132
+ cms: [
133
+ 'prettierStandalone',
134
+ 'prettierParserHtml',
135
+ 'prismCore',
136
+ 'toastify',
137
+ 'reactSelect',
138
+ 'reactBeautifulDnd',
139
+ // 'diffLib',
140
+ ],
141
+ draftEditor: [
142
+ 'immutableLib',
143
+ 'draftJs',
144
+ 'draftJsLibIsSoftNewlineEvent',
145
+ 'draftJsFilters',
146
+ 'draftJsInlineToolbarPlugin',
147
+ 'draftJsImportHtml',
148
+ 'draftJsBlockBreakoutPlugin',
149
+ ],
150
+ },
151
+ appExtras: [],
152
+ maxResponseSize: 2000000000, // This is superagent default (200 mb)
153
+ serverConfig,
154
+ storeExtenders: [],
155
+ showTags: true,
156
+ controlpanels: [],
157
+ controlPanelsIcons,
158
+ filterControlPanels,
159
+ filterControlPanelsSchema,
160
+ externalRoutes: [
161
+ // URL to be considered as external
162
+ // {
163
+ // match: {
164
+ // path: '/news',
165
+ // exact: false,
166
+ // strict: false,
167
+ // },
168
+ // url(payload) {
169
+ // return payload.location.pathname;
170
+ // },
171
+ // },
172
+ ],
173
+ showSelfRegistration: false,
174
+ contentMetadataTagsImageField: 'image',
175
+ hasWorkingCopySupport: false,
176
+ maxUndoLevels: 200, // undo history size for the main form
177
+ addonsInfo: addonsInfo,
178
+ workflowMapping,
179
+ errorHandlers: [], // callables for unhandled errors
180
+ styleClassNameConverters,
181
+ hashLinkSmoothScroll: false,
182
+ styleClassNameExtenders,
183
+ querystringSearchGet: false,
184
+ },
185
+ experimental: {
186
+ addBlockButton: {
187
+ enabled: false,
188
+ },
189
+ },
190
+ widgets: {
191
+ ...widgetMapping,
192
+ default: defaultWidget,
193
+ },
194
+ views: {
195
+ layoutViews,
196
+ contentTypesViews,
197
+ defaultView,
198
+ errorViews,
199
+ layoutViewsNamesMapping,
200
+ },
201
+ blocks: {
202
+ requiredBlocks,
203
+ blocksConfig,
204
+ groupBlocksOrder,
205
+ initialBlocks,
206
+ initialBlocksFocus,
207
+ showEditBlocksInBabelView: false,
208
+ },
209
+ addonRoutes: [],
210
+ addonReducers: {},
211
+ components,
212
+ };
213
+
214
+ ConfigRegistry.settings = config.settings;
215
+ ConfigRegistry.experimental = config.experimental;
216
+ ConfigRegistry.blocks = config.blocks;
217
+ ConfigRegistry.views = config.views;
218
+ ConfigRegistry.widgets = config.widgets;
219
+ ConfigRegistry.addonRoutes = config.addonRoutes;
220
+ ConfigRegistry.addonReducers = config.addonReducers;
221
+ ConfigRegistry.components = config.components;
222
+
223
+ applyAddonConfiguration(ConfigRegistry);
@@ -2,11 +2,13 @@ import express from 'express';
2
2
  import { getAPIResourceWithAuth } from '@plone/volto/helpers';
3
3
 
4
4
  const HEADERS = [
5
- 'Accept-Ranges',
6
- 'Cache-Control',
7
- 'Content-Disposition',
8
- 'Content-Range',
9
- 'Content-Type',
5
+ 'accept-ranges',
6
+ 'cache-control',
7
+ 'content-disposition',
8
+ 'content-range',
9
+ 'content-type',
10
+ 'x-sendfile',
11
+ 'x-accel-redirect',
10
12
  ];
11
13
 
12
14
  function filesMiddlewareFn(req, res, next) {
@@ -14,7 +16,7 @@ function filesMiddlewareFn(req, res, next) {
14
16
  .then((resource) => {
15
17
  // Just forward the headers that we need
16
18
  HEADERS.forEach((header) => {
17
- if (resource.get(header)) {
19
+ if (resource.headers[header]) {
18
20
  res.set(header, resource.get(header));
19
21
  }
20
22
  });
@@ -1,7 +1,13 @@
1
1
  import express from 'express';
2
2
  import { getAPIResourceWithAuth } from '@plone/volto/helpers';
3
3
 
4
- const HEADERS = ['content-type', 'content-disposition', 'cache-control'];
4
+ const HEADERS = [
5
+ 'content-type',
6
+ 'content-disposition',
7
+ 'cache-control',
8
+ 'x-sendfile',
9
+ 'x-accel-redirect',
10
+ ];
5
11
 
6
12
  function imageMiddlewareFn(req, res, next) {
7
13
  getAPIResourceWithAuth(req)
@@ -312,6 +312,12 @@ export const messages = defineMessages({
312
312
  id: 'flush intIds and rebuild relations',
313
313
  defaultMessage: 'flush intIds and rebuild relations',
314
314
  },
315
+ flushAndRebuildRelationsHints: {
316
+ id: 'flushAndRebuildRelationsHints',
317
+ defaultMessage:
318
+ '<ul><li>Regenerate intIds (tokens of relations in relation catalog)</li><li>Rebuild relations</li></ul><p>Check the log for details!</p><p><b>Warning</b>: If you have add-ons relying on intIds, you should not flush them.</p>',
319
+ },
320
+
315
321
  addPotentialTargetsPath: {
316
322
  id: 'target path',
317
323
  defaultMessage: 'target path',
@@ -103,7 +103,7 @@ export default function relations(state = initialState, action = {}) {
103
103
  error: null,
104
104
  relations: action.result.relations
105
105
  ? action.result.relations
106
- : state.relations,
106
+ : [],
107
107
  stats: null,
108
108
  },
109
109
  },
@@ -22,7 +22,7 @@
22
22
 
23
23
  .block .block:not(.inner)::before {
24
24
  position: absolute;
25
- z-index: -1;
25
+ z-index: auto;
26
26
  top: -9px;
27
27
  left: -9px;
28
28
  width: ~'calc(100% + 18px)';