@plone/volto 19.0.0-alpha.2 → 19.0.0-alpha.3

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 (144) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +0 -2
  3. package/cypress/downloads/downloads.html +0 -0
  4. package/locales/af.json +1 -0
  5. package/locales/ar.json +1 -0
  6. package/locales/bg.json +1 -0
  7. package/locales/bn.json +1 -0
  8. package/locales/ca/LC_MESSAGES/volto.po +39 -9
  9. package/locales/ca.json +1 -1
  10. package/locales/cs.json +1 -0
  11. package/locales/cy.json +1 -0
  12. package/locales/da.json +1 -0
  13. package/locales/de/LC_MESSAGES/volto.po +47 -17
  14. package/locales/de.json +1 -1
  15. package/locales/el.json +1 -0
  16. package/locales/en/LC_MESSAGES/volto.po +40 -10
  17. package/locales/en.json +1 -1
  18. package/locales/en_AU.json +1 -0
  19. package/locales/en_GB.json +1 -0
  20. package/locales/eo.json +1 -0
  21. package/locales/es/LC_MESSAGES/volto.po +40 -10
  22. package/locales/es.json +1 -1
  23. package/locales/et.json +1 -0
  24. package/locales/eu/LC_MESSAGES/volto.po +39 -9
  25. package/locales/eu.json +1 -1
  26. package/locales/fa.json +1 -0
  27. package/locales/fi/LC_MESSAGES/volto.po +39 -9
  28. package/locales/fi.json +1 -1
  29. package/locales/fr/LC_MESSAGES/volto.po +40 -10
  30. package/locales/fr.json +1 -1
  31. package/locales/fu.json +1 -0
  32. package/locales/gl.json +1 -0
  33. package/locales/he.json +1 -0
  34. package/locales/hi/LC_MESSAGES/volto.po +43 -13
  35. package/locales/hi.json +1 -1
  36. package/locales/hr.json +1 -0
  37. package/locales/hu.json +1 -0
  38. package/locales/hy.json +1 -0
  39. package/locales/id.json +1 -0
  40. package/locales/it/LC_MESSAGES/volto.po +43 -13
  41. package/locales/it.json +1 -1
  42. package/locales/ja/LC_MESSAGES/volto.po +39 -9
  43. package/locales/ja.json +1 -1
  44. package/locales/ka.json +1 -0
  45. package/locales/kn.json +1 -0
  46. package/locales/ko.json +1 -0
  47. package/locales/lt.json +1 -0
  48. package/locales/lv.json +1 -0
  49. package/locales/mi.json +1 -0
  50. package/locales/mk.json +1 -0
  51. package/locales/my.json +1 -0
  52. package/locales/nb_NO.json +1 -0
  53. package/locales/nl/LC_MESSAGES/volto.po +43 -13
  54. package/locales/nl.json +1 -1
  55. package/locales/nn.json +1 -0
  56. package/locales/pl.json +1 -0
  57. package/locales/pt/LC_MESSAGES/volto.po +39 -9
  58. package/locales/pt.json +1 -1
  59. package/locales/pt_BR/LC_MESSAGES/volto.po +54 -24
  60. package/locales/pt_BR.json +1 -1
  61. package/locales/rm.json +1 -0
  62. package/locales/ro/LC_MESSAGES/volto.po +43 -13
  63. package/locales/ro.json +1 -1
  64. package/locales/ru/LC_MESSAGES/volto.po +43 -13
  65. package/locales/ru.json +1 -1
  66. package/locales/sk.json +1 -0
  67. package/locales/sl.json +1 -0
  68. package/locales/sm.json +1 -0
  69. package/locales/sq.json +1 -0
  70. package/locales/sr.json +1 -0
  71. package/locales/sr@cyrl.json +1 -0
  72. package/locales/sr@latn.json +1 -0
  73. package/locales/sv.json +1 -1
  74. package/locales/ta.json +1 -0
  75. package/locales/te.json +1 -0
  76. package/locales/th.json +1 -0
  77. package/locales/to.json +1 -0
  78. package/locales/tr.json +1 -0
  79. package/locales/uk.json +1 -0
  80. package/locales/vi.json +1 -0
  81. package/locales/volto.pot +40 -10
  82. package/locales/zh_CN/LC_MESSAGES/volto.po +39 -9
  83. package/locales/zh_CN.json +1 -1
  84. package/locales/zh_Hant.json +1 -0
  85. package/locales/zh_Hant_HK.json +1 -0
  86. package/package.json +7 -7
  87. package/src/actions/content/content.js +0 -1
  88. package/src/actions/controlpanels/controlpanels.js +13 -7
  89. package/src/actions/controlpanels/controlpanels.test.js +11 -5
  90. package/src/actions/users/users.js +2 -2
  91. package/src/components/manage/Add/Add.jsx +5 -6
  92. package/src/components/manage/Blocks/Block/Edit.jsx +1 -0
  93. package/src/components/manage/Blocks/Teaser/schema.js +8 -3
  94. package/src/components/manage/Contents/Contents.jsx +3 -0
  95. package/src/components/manage/Contents/Contents.test.jsx +7 -0
  96. package/src/components/manage/Contents/ContentsBreadcrumbs.Multilingual.test.jsx +18 -5
  97. package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +20 -26
  98. package/src/components/manage/Contents/ContentsBreadcrumbs.test.jsx +14 -0
  99. package/src/components/manage/Contents/ContentsDeleteModal.jsx +258 -206
  100. package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +26 -8
  101. package/src/components/manage/Contents/ContentsItem.jsx +9 -1
  102. package/src/components/manage/Contents/ContentsUploadModal.test.jsx +13 -22
  103. package/src/components/manage/Edit/Edit.jsx +2 -3
  104. package/src/components/manage/Multilingual/CompareLanguages.jsx +2 -5
  105. package/src/components/manage/Multilingual/ManageTranslations.jsx +4 -2
  106. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +5 -1
  107. package/src/components/manage/Multilingual/TranslationObject.jsx +1 -1
  108. package/src/components/manage/Toolbar/More.jsx +4 -1
  109. package/src/components/manage/Toolbar/More.test.jsx +3 -0
  110. package/src/components/manage/Toolbar/Toolbar.jsx +3 -4
  111. package/src/components/manage/Toolbar/Types.jsx +7 -7
  112. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -3
  113. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +0 -4
  114. package/src/components/theme/App/App.jsx +3 -1
  115. package/src/components/theme/App/App.test.jsx +1 -0
  116. package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +20 -2
  117. package/src/components/theme/LanguageSelector/LanguageSelector.jsx +9 -7
  118. package/src/components/theme/LanguageSelector/LanguageSelector.test.jsx +6 -6
  119. package/src/components/theme/Logo/Logo.Multilingual.test.jsx +0 -5
  120. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +8 -12
  121. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +3 -5
  122. package/src/components/theme/Navigation/NavItem.jsx +1 -5
  123. package/src/components/theme/Navigation/Navigation.Multilingual.test.jsx +0 -5
  124. package/src/components/theme/NotFound/NotFound.jsx +5 -2
  125. package/src/components/theme/NotFound/NotFound.test.jsx +3 -0
  126. package/src/components/theme/Sitemap/Sitemap.jsx +6 -5
  127. package/src/components/theme/Sitemap/Sitemap.test.jsx +0 -1
  128. package/src/components/theme/View/FileView.jsx +9 -1
  129. package/src/config/index.js +5 -14
  130. package/src/helpers/Html/Html.jsx +0 -3
  131. package/src/helpers/LanguageMap/LanguageMap.js +115 -8
  132. package/src/middleware/Api.test.js +4 -0
  133. package/src/middleware/api.js +74 -25
  134. package/src/routes.js +1 -1
  135. package/src/server.jsx +5 -6
  136. package/src/start-client.jsx +0 -4
  137. package/test-setup-config.jsx +0 -2
  138. package/theme/themes/pastanaga/extras/blocks.less +7 -0
  139. package/theme/themes/pastanaga/extras/contents.less +5 -5
  140. package/types/components/manage/Blocks/Teaser/schema.d.ts +1 -0
  141. package/types/components/theme/FormattedDate/FormattedDate.stories.d.ts +1 -1
  142. package/types/helpers/LanguageMap/LanguageMap.d.ts +428 -4
  143. package/types/middleware/api.d.ts +6 -9
  144. package/src/actions/content/content.multilingual.test.js +0 -17
@@ -35,7 +35,7 @@ let socket = null;
35
35
  *
36
36
  * - It should add the expanders set in the config settings
37
37
  * - It should preserve any query if present
38
- * - It should preserve (and add) any expand parameter (if present) e.g. translations
38
+ * - It should preserve (and add) any expand parameter (if present)
39
39
  * - It should take use the correct codification for arrays in querystring (repeated parameter for each member of the array)
40
40
  *
41
41
  * @function addExpandersToPath
@@ -43,7 +43,7 @@ let socket = null;
43
43
  * @param {*} type The action type
44
44
  * @returns {string} The url/path with the configured expanders added to the query string
45
45
  */
46
- export function addExpandersToPath(path, type, isAnonymous) {
46
+ export function addExpandersToPath(path, type, isAnonymous, isMultilingual) {
47
47
  const { settings } = config;
48
48
  const { apiExpanders = [] } = settings;
49
49
 
@@ -58,7 +58,14 @@ export function addExpandersToPath(path, type, isAnonymous) {
58
58
 
59
59
  const expandMerge = compact(
60
60
  union([expand, ...flatten(expandersFromConfig)]),
61
- ).filter((item) => !(item === 'types' && isAnonymous)); // Remove types expander if isAnonymous
61
+ ).filter(
62
+ // Remove types for anonymous, translations unless multilingual
63
+ (item) =>
64
+ !(
65
+ (item === 'types' && isAnonymous) ||
66
+ (item === 'translations' && !isMultilingual)
67
+ ),
68
+ );
62
69
 
63
70
  const stringifiedExpand = qs.stringify(
64
71
  { expand: expandMerge },
@@ -128,6 +135,8 @@ function sendOnSocket(request) {
128
135
  * @param {Object} api Api object.
129
136
  * @returns {Promise} Action promise.
130
137
  */
138
+ let isHydrating = __CLIENT__ ? true : false;
139
+
131
140
  const apiMiddlewareFactory =
132
141
  (api) =>
133
142
  ({ dispatch, getState }) =>
@@ -135,14 +144,17 @@ const apiMiddlewareFactory =
135
144
  (action) => {
136
145
  const { settings } = config;
137
146
 
138
- const token = getState().userSession.token;
139
- let uploadedFiles = getState().content.uploadedFiles;
147
+ const state = getState();
148
+ const token = state.userSession.token;
149
+ let uploadedFiles = state.content.uploadedFiles;
150
+ const isMultilingual = state.site.data.features?.multilingual;
140
151
  let isAnonymous = true;
141
152
  if (token) {
142
153
  const tokenExpiration = jwtDecode(token).exp;
143
154
  const currentTime = new Date().getTime() / 1000;
144
155
  isAnonymous = !token || currentTime > tokenExpiration;
145
156
  }
157
+ const hasExistingError = state.content.get?.error;
146
158
 
147
159
  if (typeof action === 'function') {
148
160
  return action(dispatch, getState);
@@ -164,14 +176,24 @@ const apiMiddlewareFactory =
164
176
  request.map((item) =>
165
177
  sendOnSocket({
166
178
  ...item,
167
- path: addExpandersToPath(item.path, type, isAnonymous),
179
+ path: addExpandersToPath(
180
+ item.path,
181
+ type,
182
+ isAnonymous,
183
+ isMultilingual,
184
+ ),
168
185
  id: type,
169
186
  }),
170
187
  ),
171
188
  )
172
189
  : sendOnSocket({
173
190
  ...request,
174
- path: addExpandersToPath(request.path, type, isAnonymous),
191
+ path: addExpandersToPath(
192
+ request.path,
193
+ type,
194
+ isAnonymous,
195
+ isMultilingual,
196
+ ),
175
197
  id: type,
176
198
  });
177
199
  } else {
@@ -180,7 +202,12 @@ const apiMiddlewareFactory =
180
202
  ? request.reduce((prevPromise, item) => {
181
203
  return prevPromise.then((acc) => {
182
204
  return api[item.op](
183
- addExpandersToPath(item.path, type, isAnonymous),
205
+ addExpandersToPath(
206
+ item.path,
207
+ type,
208
+ isAnonymous,
209
+ isMultilingual,
210
+ ),
184
211
  {
185
212
  data: item.data,
186
213
  type: item.type,
@@ -201,28 +228,42 @@ const apiMiddlewareFactory =
201
228
  }, Promise.resolve([]))
202
229
  : Promise.all(
203
230
  request.map((item) =>
204
- api[item.op](addExpandersToPath(item.path, type, isAnonymous), {
205
- data: item.data,
206
- type: item.type,
207
- headers: item.headers,
208
- params: request.params,
209
- checkUrl: settings.actions_raising_api_errors.includes(
210
- action.type,
231
+ api[item.op](
232
+ addExpandersToPath(
233
+ item.path,
234
+ type,
235
+ isAnonymous,
236
+ isMultilingual,
211
237
  ),
212
- attach: item.attach,
213
- }),
238
+ {
239
+ data: item.data,
240
+ type: item.type,
241
+ headers: item.headers,
242
+ params: request.params,
243
+ checkUrl: settings.actions_raising_api_errors.includes(
244
+ action.type,
245
+ ),
246
+ attach: item.attach,
247
+ },
248
+ ),
214
249
  ),
215
250
  )
216
- : api[request.op](addExpandersToPath(request.path, type, isAnonymous), {
217
- data: request.data,
218
- type: request.type,
219
- headers: request.headers,
220
- params: request.params,
221
- checkUrl: settings.actions_raising_api_errors.includes(action.type),
222
- attach: request.attach,
223
- });
251
+ : api[request.op](
252
+ addExpandersToPath(request.path, type, isAnonymous, isMultilingual),
253
+ {
254
+ data: request.data,
255
+ type: request.type,
256
+ headers: request.headers,
257
+ params: request.params,
258
+ checkUrl: settings.actions_raising_api_errors.includes(
259
+ action.type,
260
+ ),
261
+ attach: request.attach,
262
+ },
263
+ );
224
264
  actionPromise.then(
225
265
  (result) => {
266
+ isHydrating = false;
226
267
  if (uploadedFiles !== 0) {
227
268
  dispatch(updateUploadedFiles(0));
228
269
  }
@@ -298,6 +339,14 @@ const apiMiddlewareFactory =
298
339
  }
299
340
  },
300
341
  (error) => {
342
+ // Make sure an error during hydration
343
+ // (for example when serving an archived page)
344
+ // doesn't hide the SSR content.
345
+ if (isHydrating && !hasExistingError) {
346
+ isHydrating = false;
347
+ return;
348
+ }
349
+
301
350
  // Only SSR can set ECONNREFUSED
302
351
  if (error.code === 'ECONNREFUSED') {
303
352
  next({
package/src/routes.js CHANGED
@@ -127,7 +127,7 @@ export function getExternalRoutes() {
127
127
  export const defaultRoutes = [
128
128
  // redirect to external links if path is in blacklist
129
129
  ...getExternalRoutes(),
130
- ...((config.settings?.isMultilingual && multilingualRoutes) || []),
130
+ ...(config.settings?.isMultilingual !== false ? multilingualRoutes : []),
131
131
  {
132
132
  path: '/',
133
133
  component: View,
package/src/server.jsx CHANGED
@@ -43,6 +43,7 @@ import { ReduxAsyncConnect, loadOnServer } from './helpers/AsyncConnect';
43
43
 
44
44
  let locales = {};
45
45
 
46
+ // Load locales listed in supportedLanguages setting
46
47
  if (config.settings) {
47
48
  config.settings.supportedLanguages.forEach((lang) => {
48
49
  const langFileName = toGettextLang(lang);
@@ -107,7 +108,6 @@ function setupServer(req, res, next) {
107
108
  const lang = toReactIntlLang(
108
109
  new locale.Locales(
109
110
  req.universalCookies.get('I18N_LANGUAGE') ||
110
- config.settings.defaultLanguage ||
111
111
  req.headers['accept-language'],
112
112
  )
113
113
  .best(supported)
@@ -184,7 +184,6 @@ server.get('/*', (req, res) => {
184
184
  const lang = toReactIntlLang(
185
185
  new locale.Locales(
186
186
  req.universalCookies.get('I18N_LANGUAGE') ||
187
- config.settings.defaultLanguage ||
188
187
  req.headers['accept-language'],
189
188
  )
190
189
  .best(supported)
@@ -224,9 +223,10 @@ server.get('/*', (req, res) => {
224
223
 
225
224
  loadOnServer({ store, location, routes, api })
226
225
  .then(() => {
226
+ const state = store.getState();
227
227
  const initialLang =
228
228
  req.universalCookies.get('I18N_LANGUAGE') ||
229
- config.settings.defaultLanguage ||
229
+ state.site.data['plone.default_language'] ||
230
230
  req.headers['accept-language'];
231
231
 
232
232
  // The content info is in the store at this point thanks to the asynconnect
@@ -236,10 +236,9 @@ server.get('/*', (req, res) => {
236
236
  // TODO: there is a bug here with content that, for any reason, doesn't
237
237
  // present the language token field, for some reason. In this case, we
238
238
  // should follow the cookie rather then switching the language
239
- const contentLang = store.getState().content.get?.error
239
+ const contentLang = state.content.get?.error
240
240
  ? initialLang
241
- : store.getState().content.data?.language?.token ||
242
- config.settings.defaultLanguage;
241
+ : state.content.data?.language?.token || initialLang;
243
242
 
244
243
  if (toBackendLang(initialLang) !== contentLang && url !== '/') {
245
244
  const newLang = toReactIntlLang(
@@ -58,10 +58,6 @@ export default function client() {
58
58
  if (window.env.RAZZLE_LEGACY_TRAVERSE) {
59
59
  config.settings.legacyTraverse = true;
60
60
  }
61
- // Support for setting the default language from a server environment variable
62
- if (window.env.defaultLanguage) {
63
- config.settings.defaultLanguage = window.env.defaultLanguage;
64
- }
65
61
 
66
62
  loadableReady(() => {
67
63
  hydrateRoot(
@@ -30,12 +30,10 @@ import { registerValidators } from '@plone/volto/config/validation';
30
30
  config.set('settings', {
31
31
  apiPath: 'http://localhost:8080/Plone',
32
32
  publicURL: 'http://localhost:3000',
33
- defaultLanguage: 'en',
34
33
  supportedLanguages: ['en'],
35
34
  defaultPageSize: 25,
36
35
  showTags: true,
37
36
  showRelatedItems: true,
38
- isMultilingual: false,
39
37
  nonContentRoutes,
40
38
  nonContentRoutesPublic,
41
39
  contentIcons: contentIcons,
@@ -56,6 +56,13 @@
56
56
  background-color: rgba(120, 192, 215, 0.375);
57
57
  }
58
58
 
59
+ .block.selected.error::before,
60
+ .block.selected.error:hover::before,
61
+ .block.error:hover::before,
62
+ .block.error::before {
63
+ border-color: #ff0000 !important;
64
+ }
65
+
59
66
  #toolbar .toolbar-actions .blockCount {
60
67
  position: absolute;
61
68
  margin-top: 18px;
@@ -149,8 +149,12 @@
149
149
  .ui.table .button-margin {
150
150
  padding: 4px;
151
151
  margin-right: 1em;
152
- background-color: rgb(228, 1, 102);
152
+ background-color: #007eb1;
153
153
  color: white;
154
+
155
+ &.expired-past {
156
+ background-color: rgb(228, 1, 102);
157
+ }
154
158
  }
155
159
  }
156
160
 
@@ -185,10 +189,6 @@
185
189
  white-space: normal;
186
190
  word-break: break-all;
187
191
  }
188
-
189
- .broken-links-list {
190
- margin-top: 30px;
191
- }
192
192
  }
193
193
 
194
194
  .contenttype-event {
@@ -27,6 +27,7 @@ export function TeaserSchema({ data, intl }: {
27
27
  };
28
28
  head_title: {
29
29
  title: any;
30
+ description: any;
30
31
  };
31
32
  description: {
32
33
  title: any;
@@ -10,9 +10,9 @@ declare namespace _default {
10
10
  export let decorators: ((Story: any) => import("react/jsx-runtime").JSX.Element)[];
11
11
  export namespace argTypes {
12
12
  namespace locale {
13
+ let options: string[];
13
14
  namespace control {
14
15
  let type: string;
15
- let options: string[];
16
16
  }
17
17
  }
18
18
  }