@plone/volto 16.22.0 → 16.22.1

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 (68) hide show
  1. package/.changelog.draft +15 -22
  2. package/.gitignore~ +71 -0
  3. package/.yarn/install-state.gz +0 -0
  4. package/CHANGELOG.md +27 -1
  5. package/locales/ca/LC_MESSAGES/volto.po +37 -2
  6. package/locales/ca.json +1 -1
  7. package/locales/de/LC_MESSAGES/volto.po +38 -3
  8. package/locales/de.json +1 -1
  9. package/locales/en/LC_MESSAGES/volto.po +37 -2
  10. package/locales/en.json +1 -1
  11. package/locales/es/LC_MESSAGES/volto.po +37 -2
  12. package/locales/es.json +1 -1
  13. package/locales/eu/LC_MESSAGES/volto.po +37 -2
  14. package/locales/eu.json +1 -1
  15. package/locales/fi/LC_MESSAGES/volto.po +37 -2
  16. package/locales/fi.json +1 -1
  17. package/locales/fr/LC_MESSAGES/volto.po +37 -2
  18. package/locales/fr.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +228 -193
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +37 -2
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +37 -2
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +37 -2
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +37 -2
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +37 -2
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +38 -3
  32. package/locales/volto.pot~ +4705 -0
  33. package/locales/zh_CN/LC_MESSAGES/volto.po +37 -2
  34. package/locales/zh_CN.json +1 -1
  35. package/news/4547.breaking~ +1 -0
  36. package/package.json +1 -1
  37. package/package.json~ +444 -0
  38. package/packages/volto-slate/package.json +1 -1
  39. package/src/components/manage/Blocks/Image/schema.js +5 -1
  40. package/src/components/manage/Blocks/Search/components/SearchInput.jsx +9 -2
  41. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +12 -1
  42. package/src/components/manage/Blocks/ToC/Schema.jsx +36 -7
  43. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +1 -13
  44. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +2 -2
  45. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +2 -2
  46. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +25 -10
  47. package/src/components/manage/Widgets/SelectUtils.js +1 -1
  48. package/src/components/theme/Error/ServerError.jsx +29 -0
  49. package/src/config/Views.jsx +2 -0
  50. package/src/config/index.js~ +223 -0
  51. package/src/express-middleware/files.js +8 -6
  52. package/src/express-middleware/images.js +7 -1
  53. package/src/middleware/api.js +14 -2
  54. package/src/reducers/actions/actions.js +7 -5
  55. package/src/reducers/actions/actions.test.js +70 -0
  56. package/src/server.jsx +9 -0
  57. package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +0 -90
  58. package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +0 -6
  59. package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +0 -6
  60. package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +0 -6
  61. package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +0 -10
  62. package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +0 -10
  63. package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +0 -30
  64. package/packages/volto-slate/build/messages/src/elementEditor/messages.json +0 -10
  65. package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +0 -6
  66. package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +0 -6
  67. package/pyvenv.cfg +0 -3
  68. package/share/man/man1/ttx.1 +0 -225
@@ -107,6 +107,7 @@ class UsersControlpanel extends Component {
107
107
  isClient: false,
108
108
  currentPage: 0,
109
109
  pageSize: 10,
110
+ loginUsingEmail: false,
110
111
  };
111
112
  }
112
113
 
@@ -122,6 +123,14 @@ class UsersControlpanel extends Component {
122
123
  }
123
124
  };
124
125
 
126
+ // Because username field needs to be disabled if email login is enabled!
127
+ checkLoginUsingEmailStatus = async () => {
128
+ await this.props.getControlpanel('security');
129
+ this.setState({
130
+ loginUsingEmail: this.props.controlPanelData?.data.use_email_as_login,
131
+ });
132
+ };
133
+
125
134
  /**
126
135
  * Component did mount
127
136
  * @method componentDidMount
@@ -132,6 +141,7 @@ class UsersControlpanel extends Component {
132
141
  isClient: true,
133
142
  });
134
143
  this.fetchData();
144
+ this.checkLoginUsingEmailStatus();
135
145
  }
136
146
 
137
147
  UNSAFE_componentWillReceiveProps(nextProps) {
@@ -425,7 +435,7 @@ class UsersControlpanel extends Component {
425
435
  id: 'default',
426
436
  title: 'FIXME: User Data',
427
437
  fields: [
428
- 'username',
438
+ ...(!this.state.loginUsingEmail ? ['username'] : []),
429
439
  'fullname',
430
440
  'email',
431
441
  'password',
@@ -436,15 +446,19 @@ class UsersControlpanel extends Component {
436
446
  },
437
447
  ],
438
448
  properties: {
439
- username: {
440
- title: this.props.intl.formatMessage(
441
- messages.addUserFormUsernameTitle,
442
- ),
443
- type: 'string',
444
- description: this.props.intl.formatMessage(
445
- messages.addUserFormUsernameDescription,
446
- ),
447
- },
449
+ ...(!this.state.loginUsingEmail
450
+ ? {
451
+ username: {
452
+ title: this.props.intl.formatMessage(
453
+ messages.addUserFormUsernameTitle,
454
+ ),
455
+ type: 'string',
456
+ description: this.props.intl.formatMessage(
457
+ messages.addUserFormUsernameDescription,
458
+ ),
459
+ },
460
+ }
461
+ : {}),
448
462
  fullname: {
449
463
  title: this.props.intl.formatMessage(
450
464
  messages.addUserFormFullnameTitle,
@@ -670,6 +684,7 @@ export default compose(
670
684
  createRequest: state.users.create,
671
685
  loadRolesRequest: state.roles,
672
686
  inheritedRole: state.authRole.authenticatedRole,
687
+ controlPanelData: state.controlpanels?.controlpanel,
673
688
  }),
674
689
  (dispatch) =>
675
690
  bindActionCreators(
@@ -111,7 +111,7 @@ export function normalizeValue(choices, value, intl) {
111
111
 
112
112
  if (Array.isArray(value)) {
113
113
  // a list of values, like ['foo', 'bar'];
114
- return value.map((v) => normalizeValue(choices, v));
114
+ return value.map((v) => normalizeValue(choices, v, intl));
115
115
  }
116
116
 
117
117
  if (isObject(value)) {
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @module components/theme/Error/ServerError
3
+ */
4
+
5
+ import React from 'react';
6
+ import { FormattedMessage } from 'react-intl';
7
+ import { Container } from 'semantic-ui-react';
8
+ import { withServerErrorCode } from '@plone/volto/helpers/Utils/Utils';
9
+
10
+ /**
11
+ * server error
12
+ * @function ServerError
13
+ * @returns {string} Markup of the server error page.
14
+ */
15
+ const ServerError = () => (
16
+ <Container className="view-wrapper">
17
+ <h1>
18
+ <FormattedMessage id="Server Error" defaultMessage="Server Error" />
19
+ </h1>
20
+ <p className="description">
21
+ <FormattedMessage
22
+ id="We apologize for the inconvenience, but there was an unexpected error on the server."
23
+ defaultMessage="We apologize for the inconvenience, but there was an unexpected error on the server."
24
+ />
25
+ </p>
26
+ </Container>
27
+ );
28
+
29
+ export default withServerErrorCode(500)(ServerError);
@@ -16,6 +16,7 @@ import RequestTimeout from '@plone/volto/components/theme/RequestTimeout/Request
16
16
  import AlbumView from '@plone/volto/components/theme/View/AlbumView';
17
17
  import Unauthorized from '@plone/volto/components/theme/Unauthorized/Unauthorized';
18
18
  import Forbidden from '@plone/volto/components/theme/Forbidden/Forbidden';
19
+ import ServerError from '@plone/volto/components/theme/Error/ServerError';
19
20
 
20
21
  const EventView = loadable(() =>
21
22
  import('@plone/volto/components/theme/View/EventView'),
@@ -114,6 +115,7 @@ export const errorViews = {
114
115
  '401': Unauthorized,
115
116
  '403': Forbidden,
116
117
  '408': RequestTimeout,
118
+ '500': ServerError,
117
119
  ECONNREFUSED: ConnectionRefused,
118
120
  corsError: CorsError,
119
121
  };
@@ -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)
@@ -250,10 +250,22 @@ const apiMiddlewareFactory = (api) => ({ dispatch, getState }) => (next) => (
250
250
  };
251
251
  });
252
252
  }
253
- return next({ ...rest, result, type: `${type}_SUCCESS` });
253
+ try {
254
+ return next({ ...rest, result, type: `${type}_SUCCESS` });
255
+ } catch (error) {
256
+ // There was an exception while processing reducers or downstream middleware.
257
+ next({
258
+ ...rest,
259
+ error: { status: 500, error },
260
+ type: `${type}_FAIL`,
261
+ });
262
+ // Rethrow the original exception on the client side only,
263
+ // so it doesn't fall through to express on the server.
264
+ if (__CLIENT__) throw error;
265
+ }
254
266
  },
255
267
  (error) => {
256
- // Only SRR can set ECONNREFUSED
268
+ // Only SSR can set ECONNREFUSED
257
269
  if (error.code === 'ECONNREFUSED') {
258
270
  next({
259
271
  ...rest,
@@ -57,11 +57,13 @@ export default function actions(state = initialState, action = {}) {
57
57
  }
58
58
  return state;
59
59
  case `${LIST_ACTIONS}_SUCCESS`:
60
- hasExpander = hasApiExpander(
61
- 'actions',
62
- getBaseUrl(flattenToAppURL(action.result['@id'])),
63
- );
64
- if (!hasExpander) {
60
+ // Even if the expander is set or not, if the LIST_ACTIONS is
61
+ // called, we want it to store the data if the actions data is
62
+ // not set in the expander data (['@components']) but in the "normal"
63
+ // action result (we look for the object property returned by the endpoint)
64
+ // Unfortunately, this endpoint returns all the actions in a plain object
65
+ // with no structure :(
66
+ if (action.result.object) {
65
67
  return {
66
68
  ...state,
67
69
  error: null,
@@ -207,4 +207,74 @@ describe('Actions reducer - (ACTIONS)GET_CONTENT', () => {
207
207
  loading: false,
208
208
  });
209
209
  });
210
+
211
+ it('should handle (ACTIONS)LIST_ACTIONS (standalone with apiExpander enabled)', () => {
212
+ expect(
213
+ actions(undefined, {
214
+ type: `${LIST_ACTIONS}_SUCCESS`,
215
+ result: {
216
+ object: [],
217
+ object_buttons: [],
218
+ site_actions: [],
219
+ user: [
220
+ {
221
+ icon: '',
222
+ id: 'preferences',
223
+ title: 'Preferences',
224
+ },
225
+ {
226
+ icon: '',
227
+ id: 'dashboard',
228
+ title: 'Dashboard',
229
+ },
230
+ {
231
+ icon: '',
232
+ id: 'plone_setup',
233
+ title: 'Site Setup',
234
+ },
235
+ {
236
+ icon: '',
237
+ id: 'logout',
238
+ title: 'Log out',
239
+ },
240
+ ],
241
+ document_actions: [],
242
+ portal_tabs: [],
243
+ },
244
+ }),
245
+ ).toEqual({
246
+ error: null,
247
+ actions: {
248
+ object: [],
249
+ object_buttons: [],
250
+ site_actions: [],
251
+ user: [
252
+ {
253
+ icon: '',
254
+ id: 'preferences',
255
+ title: 'Preferences',
256
+ },
257
+ {
258
+ icon: '',
259
+ id: 'dashboard',
260
+ title: 'Dashboard',
261
+ },
262
+ {
263
+ icon: '',
264
+ id: 'plone_setup',
265
+ title: 'Site Setup',
266
+ },
267
+ {
268
+ icon: '',
269
+ id: 'logout',
270
+ title: 'Log out',
271
+ },
272
+ ],
273
+ document_actions: [],
274
+ portal_tabs: [],
275
+ },
276
+ loaded: true,
277
+ loading: false,
278
+ });
279
+ });
210
280
  });
package/src/server.jsx CHANGED
@@ -263,6 +263,15 @@ server.get('/*', (req, res) => {
263
263
  const readCriticalCss =
264
264
  config.settings.serverConfig.readCriticalCss || defaultReadCriticalCss;
265
265
 
266
+ // If we are showing an "old browser" warning,
267
+ // make sure it doesn't get cached in a shared cache
268
+ const browserdetect = store.getState().browserdetect;
269
+ if (config.settings.notSupportedBrowsers.includes(browserdetect?.name)) {
270
+ res.set({
271
+ 'Cache-Control': 'private',
272
+ });
273
+ }
274
+
266
275
  if (context.url) {
267
276
  res.redirect(flattenToAppURL(context.url));
268
277
  } else if (context.error_code) {
@@ -1,90 +0,0 @@
1
- [
2
- {
3
- "id": "Insert row before",
4
- "defaultMessage": "Insert row before"
5
- },
6
- {
7
- "id": "Insert row after",
8
- "defaultMessage": "Insert row after"
9
- },
10
- {
11
- "id": "Delete row",
12
- "defaultMessage": "Delete row"
13
- },
14
- {
15
- "id": "Insert col before",
16
- "defaultMessage": "Insert col before"
17
- },
18
- {
19
- "id": "Insert col after",
20
- "defaultMessage": "Insert col after"
21
- },
22
- {
23
- "id": "Delete col",
24
- "defaultMessage": "Delete col"
25
- },
26
- {
27
- "id": "Hide headers",
28
- "defaultMessage": "Hide headers"
29
- },
30
- {
31
- "id": "Make the table sortable",
32
- "defaultMessage": "Make the table sortable"
33
- },
34
- {
35
- "id": "Visible only in view mode",
36
- "defaultMessage": "Visible only in view mode"
37
- },
38
- {
39
- "id": "Fixed width table cells",
40
- "defaultMessage": "Fixed width table cells"
41
- },
42
- {
43
- "id": "Make the table compact",
44
- "defaultMessage": "Make the table compact"
45
- },
46
- {
47
- "id": "Reduce complexity",
48
- "defaultMessage": "Reduce complexity"
49
- },
50
- {
51
- "id": "Divide each row into separate cells",
52
- "defaultMessage": "Divide each row into separate cells"
53
- },
54
- {
55
- "id": "Table color inverted",
56
- "defaultMessage": "Table color inverted"
57
- },
58
- {
59
- "id": "Stripe alternate rows with color",
60
- "defaultMessage": "Stripe alternate rows with color"
61
- },
62
- {
63
- "id": "Left",
64
- "defaultMessage": "Left"
65
- },
66
- {
67
- "id": "Center",
68
- "defaultMessage": "Center"
69
- },
70
- {
71
- "id": "Right",
72
- "defaultMessage": "Right"
73
- },
74
- {
75
- "id": "Bottom",
76
- "defaultMessage": "Bottom"
77
- },
78
- {
79
- "id": "Middle",
80
- "defaultMessage": "Middle"
81
- },
82
- {
83
- "id": "Top",
84
- "defaultMessage": "Top"
85
- },
86
- {
87
- "id": "Table",
88
- "defaultMessage": "Table"
89
- }
90
- ]
@@ -1,6 +0,0 @@
1
- [
2
- {
3
- "id": "Type text…",
4
- "defaultMessage": "Type text…"
5
- }
6
- ]
@@ -1,6 +0,0 @@
1
- [
2
- {
3
- "id": "Type text…",
4
- "defaultMessage": "Type text…"
5
- }
6
- ]
@@ -1,6 +0,0 @@
1
- [
2
- {
3
- "id": "No matching blocks",
4
- "defaultMessage": "No matching blocks"
5
- }
6
- ]
@@ -1,10 +0,0 @@
1
- [
2
- {
3
- "id": "Edit link",
4
- "defaultMessage": "Edit link"
5
- },
6
- {
7
- "id": "Remove link",
8
- "defaultMessage": "Remove link"
9
- }
10
- ]
@@ -1,10 +0,0 @@
1
- [
2
- {
3
- "id": "Add link",
4
- "defaultMessage": "Add link"
5
- },
6
- {
7
- "id": "Edit link",
8
- "defaultMessage": "Edit link"
9
- }
10
- ]