@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.
- package/CHANGELOG.md +37 -0
- package/README.md +0 -2
- package/cypress/downloads/downloads.html +0 -0
- package/locales/af.json +1 -0
- package/locales/ar.json +1 -0
- package/locales/bg.json +1 -0
- package/locales/bn.json +1 -0
- package/locales/ca/LC_MESSAGES/volto.po +39 -9
- package/locales/ca.json +1 -1
- package/locales/cs.json +1 -0
- package/locales/cy.json +1 -0
- package/locales/da.json +1 -0
- package/locales/de/LC_MESSAGES/volto.po +47 -17
- package/locales/de.json +1 -1
- package/locales/el.json +1 -0
- package/locales/en/LC_MESSAGES/volto.po +40 -10
- package/locales/en.json +1 -1
- package/locales/en_AU.json +1 -0
- package/locales/en_GB.json +1 -0
- package/locales/eo.json +1 -0
- package/locales/es/LC_MESSAGES/volto.po +40 -10
- package/locales/es.json +1 -1
- package/locales/et.json +1 -0
- package/locales/eu/LC_MESSAGES/volto.po +39 -9
- package/locales/eu.json +1 -1
- package/locales/fa.json +1 -0
- package/locales/fi/LC_MESSAGES/volto.po +39 -9
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +40 -10
- package/locales/fr.json +1 -1
- package/locales/fu.json +1 -0
- package/locales/gl.json +1 -0
- package/locales/he.json +1 -0
- package/locales/hi/LC_MESSAGES/volto.po +43 -13
- package/locales/hi.json +1 -1
- package/locales/hr.json +1 -0
- package/locales/hu.json +1 -0
- package/locales/hy.json +1 -0
- package/locales/id.json +1 -0
- package/locales/it/LC_MESSAGES/volto.po +43 -13
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +39 -9
- package/locales/ja.json +1 -1
- package/locales/ka.json +1 -0
- package/locales/kn.json +1 -0
- package/locales/ko.json +1 -0
- package/locales/lt.json +1 -0
- package/locales/lv.json +1 -0
- package/locales/mi.json +1 -0
- package/locales/mk.json +1 -0
- package/locales/my.json +1 -0
- package/locales/nb_NO.json +1 -0
- package/locales/nl/LC_MESSAGES/volto.po +43 -13
- package/locales/nl.json +1 -1
- package/locales/nn.json +1 -0
- package/locales/pl.json +1 -0
- package/locales/pt/LC_MESSAGES/volto.po +39 -9
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +54 -24
- package/locales/pt_BR.json +1 -1
- package/locales/rm.json +1 -0
- package/locales/ro/LC_MESSAGES/volto.po +43 -13
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +43 -13
- package/locales/ru.json +1 -1
- package/locales/sk.json +1 -0
- package/locales/sl.json +1 -0
- package/locales/sm.json +1 -0
- package/locales/sq.json +1 -0
- package/locales/sr.json +1 -0
- package/locales/sr@cyrl.json +1 -0
- package/locales/sr@latn.json +1 -0
- package/locales/sv.json +1 -1
- package/locales/ta.json +1 -0
- package/locales/te.json +1 -0
- package/locales/th.json +1 -0
- package/locales/to.json +1 -0
- package/locales/tr.json +1 -0
- package/locales/uk.json +1 -0
- package/locales/vi.json +1 -0
- package/locales/volto.pot +40 -10
- package/locales/zh_CN/LC_MESSAGES/volto.po +39 -9
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant.json +1 -0
- package/locales/zh_Hant_HK.json +1 -0
- package/package.json +7 -7
- package/src/actions/content/content.js +0 -1
- package/src/actions/controlpanels/controlpanels.js +13 -7
- package/src/actions/controlpanels/controlpanels.test.js +11 -5
- package/src/actions/users/users.js +2 -2
- package/src/components/manage/Add/Add.jsx +5 -6
- package/src/components/manage/Blocks/Block/Edit.jsx +1 -0
- package/src/components/manage/Blocks/Teaser/schema.js +8 -3
- package/src/components/manage/Contents/Contents.jsx +3 -0
- package/src/components/manage/Contents/Contents.test.jsx +7 -0
- package/src/components/manage/Contents/ContentsBreadcrumbs.Multilingual.test.jsx +18 -5
- package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +20 -26
- package/src/components/manage/Contents/ContentsBreadcrumbs.test.jsx +14 -0
- package/src/components/manage/Contents/ContentsDeleteModal.jsx +258 -206
- package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +26 -8
- package/src/components/manage/Contents/ContentsItem.jsx +9 -1
- package/src/components/manage/Contents/ContentsUploadModal.test.jsx +13 -22
- package/src/components/manage/Edit/Edit.jsx +2 -3
- package/src/components/manage/Multilingual/CompareLanguages.jsx +2 -5
- package/src/components/manage/Multilingual/ManageTranslations.jsx +4 -2
- package/src/components/manage/Multilingual/ManageTranslations.test.jsx +5 -1
- package/src/components/manage/Multilingual/TranslationObject.jsx +1 -1
- package/src/components/manage/Toolbar/More.jsx +4 -1
- package/src/components/manage/Toolbar/More.test.jsx +3 -0
- package/src/components/manage/Toolbar/Toolbar.jsx +3 -4
- package/src/components/manage/Toolbar/Types.jsx +7 -7
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -3
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +0 -4
- package/src/components/theme/App/App.jsx +3 -1
- package/src/components/theme/App/App.test.jsx +1 -0
- package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +20 -2
- package/src/components/theme/LanguageSelector/LanguageSelector.jsx +9 -7
- package/src/components/theme/LanguageSelector/LanguageSelector.test.jsx +6 -6
- package/src/components/theme/Logo/Logo.Multilingual.test.jsx +0 -5
- package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +8 -12
- package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +3 -5
- package/src/components/theme/Navigation/NavItem.jsx +1 -5
- package/src/components/theme/Navigation/Navigation.Multilingual.test.jsx +0 -5
- package/src/components/theme/NotFound/NotFound.jsx +5 -2
- package/src/components/theme/NotFound/NotFound.test.jsx +3 -0
- package/src/components/theme/Sitemap/Sitemap.jsx +6 -5
- package/src/components/theme/Sitemap/Sitemap.test.jsx +0 -1
- package/src/components/theme/View/FileView.jsx +9 -1
- package/src/config/index.js +5 -14
- package/src/helpers/Html/Html.jsx +0 -3
- package/src/helpers/LanguageMap/LanguageMap.js +115 -8
- package/src/middleware/Api.test.js +4 -0
- package/src/middleware/api.js +74 -25
- package/src/routes.js +1 -1
- package/src/server.jsx +5 -6
- package/src/start-client.jsx +0 -4
- package/test-setup-config.jsx +0 -2
- package/theme/themes/pastanaga/extras/blocks.less +7 -0
- package/theme/themes/pastanaga/extras/contents.less +5 -5
- package/types/components/manage/Blocks/Teaser/schema.d.ts +1 -0
- package/types/components/theme/FormattedDate/FormattedDate.stories.d.ts +1 -1
- package/types/helpers/LanguageMap/LanguageMap.d.ts +428 -4
- package/types/middleware/api.d.ts +6 -9
- package/src/actions/content/content.multilingual.test.js +0 -17
package/src/middleware/api.js
CHANGED
|
@@ -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)
|
|
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(
|
|
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
|
|
139
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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](
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
action.type,
|
|
231
|
+
api[item.op](
|
|
232
|
+
addExpandersToPath(
|
|
233
|
+
item.path,
|
|
234
|
+
type,
|
|
235
|
+
isAnonymous,
|
|
236
|
+
isMultilingual,
|
|
211
237
|
),
|
|
212
|
-
|
|
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](
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
...(
|
|
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
|
-
|
|
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 =
|
|
239
|
+
const contentLang = state.content.get?.error
|
|
240
240
|
? initialLang
|
|
241
|
-
:
|
|
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(
|
package/src/start-client.jsx
CHANGED
|
@@ -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(
|
package/test-setup-config.jsx
CHANGED
|
@@ -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:
|
|
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 {
|
|
@@ -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
|
}
|