@plone/volto 16.33.0 → 16.34.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.
package/.changelog.draft CHANGED
@@ -1,22 +1,7 @@
1
- ## 16.33.0 (2024-10-23)
2
-
3
- ### Feature
4
-
5
- - URL Management control panel: add a filter for redirects created after a given date.
6
- **Note:** This requires `Products.CMFPlone` 6.0.14 and `plone.restapi` 9.7.3 or later.
7
- @davisagli [#6414](https://github.com/plone/volto/issues/6414)
8
- - URL Management control panel: Move the form for adding a new redirect into a modal. @davisagli [#6421](https://github.com/plone/volto/issues/6421)
9
- - URL Management control panel: Add feature to bulk upload redirects in a CSV file.
10
- **Note:** This requires `plone.restapi` 9.7.3 or later.
11
- @davisagli [#6421](https://github.com/plone/volto/issues/6421)
12
- - URL Management control panel: Add a way to edit existing aliases. @davisagli [#6425](https://github.com/plone/volto/issues/6425)
1
+ ## 16.34.1 (2025-09-29)
13
2
 
14
3
  ### Bugfix
15
4
 
16
- - URL Management control panel: Improve layout for long paths. @davisagli [#6421](https://github.com/plone/volto/issues/6421)
17
-
18
- ### Internal
19
-
20
- - Update upload-artifact action to fix CI. @davisagli [#6432](https://github.com/plone/volto/issues/6432)
5
+ - Added guard in API REDUX middleware. @sneridagh [#7412](https://github.com/plone/volto/issues/7412)
21
6
 
22
7
 
package/.readthedocs.yaml CHANGED
@@ -3,8 +3,7 @@ build:
3
3
  os: "ubuntu-22.04"
4
4
  tools:
5
5
  python: "3.12"
6
- jobs:
7
- post_checkout:
8
- # Cancel the Read the Docs build
9
- # https://docs.readthedocs.io/en/stable/build-customization.html#cancel-build-based-on-a-condition
10
- - exit 183;
6
+ commands:
7
+ # Cancel the Read the Docs build
8
+ # https://docs.readthedocs.io/en/stable/build-customization.html#cancel-build-based-on-a-condition
9
+ - exit 183;
Binary file
package/CHANGELOG.md CHANGED
@@ -8,6 +8,22 @@
8
8
 
9
9
  <!-- towncrier release notes start -->
10
10
 
11
+ ## 16.34.1 (2025-09-29)
12
+
13
+ ### Bugfix
14
+
15
+ - Added guard in API REDUX middleware. @sneridagh [#7412](https://github.com/plone/volto/issues/7412)
16
+
17
+ ## 16.34.0 (2025-08-25)
18
+
19
+ ### Feature
20
+
21
+ - Provide language alternate links @erral [#6615](https://github.com/plone/volto/issues/6615)
22
+
23
+ ### Bugfix
24
+
25
+ - Fix corner case in devproxy when pathname is null. @sneridagh [#7276](https://github.com/plone/volto/issues/7276)
26
+
11
27
  ## 16.33.0 (2024-10-23)
12
28
 
13
29
  ### Feature
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "16.33.0",
12
+ "version": "16.34.1",
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "git@github.com:plone/volto.git"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plone/volto-slate",
3
- "version": "16.33.0",
3
+ "version": "16.34.1",
4
4
  "description": "Slate.js integration with Volto",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,23 @@
1
+ import config from '@plone/volto/registry';
2
+ import Helmet from '@plone/volto/helpers/Helmet/Helmet';
3
+
4
+ const AlternateHrefLangs = (props) => {
5
+ const { content } = props;
6
+ return (
7
+ <Helmet>
8
+ {config.settings.isMultilingual &&
9
+ content['@components']?.translations?.items?.map((item, key) => {
10
+ return (
11
+ <link
12
+ key={key}
13
+ rel="alternate"
14
+ hrefLang={item.language}
15
+ href={item['@id']}
16
+ />
17
+ );
18
+ })}
19
+ </Helmet>
20
+ );
21
+ };
22
+
23
+ export { AlternateHrefLangs };
@@ -0,0 +1,135 @@
1
+ import React from 'react';
2
+ import Helmet from '@plone/volto/helpers/Helmet/Helmet';
3
+
4
+ import renderer from 'react-test-renderer';
5
+ import configureStore from 'redux-mock-store';
6
+ import { Provider } from 'react-intl-redux';
7
+ import config from '@plone/volto/registry';
8
+
9
+ import { AlternateHrefLangs } from './AlternateHrefLangs';
10
+
11
+ const mockStore = configureStore();
12
+
13
+ describe('AlternateHrefLangs', () => {
14
+ beforeEach(() => {});
15
+ it('non multilingual site, renders nothing', () => {
16
+ config.settings.isMultilingual = false;
17
+ const content = {
18
+ '@id': '/',
19
+ '@components': {},
20
+ };
21
+ const store = mockStore({
22
+ intl: {
23
+ locale: 'en',
24
+ messages: {},
25
+ },
26
+ });
27
+ // We need to force the component rendering
28
+ // to fill the Helmet
29
+ renderer.create(
30
+ <Provider store={store}>
31
+ <AlternateHrefLangs content={content} />
32
+ </Provider>,
33
+ );
34
+
35
+ const helmetLinks = Helmet.peek().linkTags;
36
+ expect(helmetLinks.length).toBe(0);
37
+ });
38
+ it('multilingual site, with some translations', () => {
39
+ config.settings.isMultilingual = true;
40
+ config.settings.supportedLanguages = ['en', 'es', 'eu'];
41
+
42
+ const content = {
43
+ '@components': {
44
+ translations: {
45
+ items: [
46
+ { '@id': '/en', language: 'en' },
47
+ { '@id': '/es', language: 'es' },
48
+ ],
49
+ },
50
+ },
51
+ };
52
+
53
+ const store = mockStore({
54
+ intl: {
55
+ locale: 'en',
56
+ messages: {},
57
+ },
58
+ });
59
+
60
+ // We need to force the component rendering
61
+ // to fill the Helmet
62
+ renderer.create(
63
+ <Provider store={store}>
64
+ <>
65
+ <AlternateHrefLangs content={content} />
66
+ </>
67
+ </Provider>,
68
+ );
69
+ const helmetLinks = Helmet.peek().linkTags;
70
+
71
+ expect(helmetLinks.length).toBe(2);
72
+
73
+ expect(helmetLinks).toContainEqual({
74
+ rel: 'alternate',
75
+ href: '/es',
76
+ hrefLang: 'es',
77
+ });
78
+ expect(helmetLinks).toContainEqual({
79
+ rel: 'alternate',
80
+ href: '/en',
81
+ hrefLang: 'en',
82
+ });
83
+ });
84
+ it('multilingual site, with all available translations', () => {
85
+ config.settings.isMultilingual = true;
86
+ config.settings.supportedLanguages = ['en', 'es', 'eu'];
87
+ const store = mockStore({
88
+ intl: {
89
+ locale: 'en',
90
+ messages: {},
91
+ },
92
+ });
93
+
94
+ const content = {
95
+ '@components': {
96
+ translations: {
97
+ items: [
98
+ { '@id': '/en', language: 'en' },
99
+ { '@id': '/eu', language: 'eu' },
100
+ { '@id': '/es', language: 'es' },
101
+ ],
102
+ },
103
+ },
104
+ };
105
+
106
+ // We need to force the component rendering
107
+ // to fill the Helmet
108
+ renderer.create(
109
+ <Provider store={store}>
110
+ <AlternateHrefLangs content={content} />
111
+ </Provider>,
112
+ );
113
+
114
+ const helmetLinks = Helmet.peek().linkTags;
115
+
116
+ // We expect having 3 links
117
+ expect(helmetLinks.length).toBe(3);
118
+
119
+ expect(helmetLinks).toContainEqual({
120
+ rel: 'alternate',
121
+ href: '/eu',
122
+ hrefLang: 'eu',
123
+ });
124
+ expect(helmetLinks).toContainEqual({
125
+ rel: 'alternate',
126
+ href: '/es',
127
+ hrefLang: 'es',
128
+ });
129
+ expect(helmetLinks).toContainEqual({
130
+ rel: 'alternate',
131
+ href: '/en',
132
+ hrefLang: 'en',
133
+ });
134
+ });
135
+ });
@@ -18,6 +18,7 @@ import {
18
18
  Tags,
19
19
  Toolbar,
20
20
  } from '@plone/volto/components';
21
+ import { AlternateHrefLangs } from '@plone/volto/components/theme/AlternateHrefLangs/AlternateHrefLangs';
21
22
  import { listActions, getContent } from '@plone/volto/actions';
22
23
  import {
23
24
  BodyClass,
@@ -236,6 +237,7 @@ class View extends Component {
236
237
  return (
237
238
  <div id="view">
238
239
  <ContentMetadataTags content={this.props.content} />
240
+ <AlternateHrefLangs content={this.props.content} />
239
241
  {/* Body class if displayName in component is set */}
240
242
  <BodyClass
241
243
  className={
@@ -10,8 +10,13 @@ import querystring from 'querystring';
10
10
  import { parse as parseUrl } from 'url';
11
11
 
12
12
  const filter = function (pathname, req) {
13
- // This is the proxy to the API in case the accept header is 'application/json'
14
- return config.settings.devProxyToApiPath && pathname.startsWith('/++api++');
13
+ // Check if pathname is defined, there are some corner cases that pathname is null
14
+ if (pathname) {
15
+ // This is the proxy to the API in case the accept header is 'application/json'
16
+ return config.settings.devProxyToApiPath && pathname.startsWith('/++api++');
17
+ } else {
18
+ return false;
19
+ }
15
20
  };
16
21
 
17
22
  let _env = null;
@@ -331,7 +331,7 @@ const apiMiddlewareFactory = (api) => ({ dispatch, getState }) => (next) => (
331
331
  ...rest,
332
332
  error,
333
333
  statusCode: error.response,
334
- message: error.response.body.message,
334
+ message: error.response?.body?.message,
335
335
  connectionRefused: false,
336
336
  type: SET_APIERROR,
337
337
  });
package/.python-version DELETED
@@ -1 +0,0 @@
1
- 3.9.13
@@ -1,7 +0,0 @@
1
- # Packages
2
-
3
- This directory is intended to contain packages related to Volto ecosystem.
4
-
5
- It was never intended to convert this repo in a monorepo.
6
-
7
- Main Volto package is still located in the root, and it's intended to continue doing so.