@eeacms/volto-eea-website-theme 4.0.1 → 4.0.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 +8 -1
- package/package.json +1 -1
- package/src/actions/navigation.js +1 -1
- package/src/actions/navigation.test.js +1 -1
- package/src/customizations/@plone/volto-slate/blocks/Table/TableBlockView.jsx +0 -1
- package/src/customizations/volto/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +36 -0
- package/src/customizations/volto/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +223 -0
- package/src/customizations/volto/server.jsx +1 -1
- package/src/reducers/navigation/navigation.js +1 -1
- package/src/reducers/navigation/navigation.test.js +1 -1
- package/src/reducers/navigation.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
### [4.0.3](https://github.com/eea/volto-eea-website-theme/compare/4.0.2...4.0.3) - 8 April 2026
|
|
8
|
+
|
|
9
|
+
#### :bug: Bug Fixes
|
|
10
|
+
|
|
11
|
+
- fix: crash in AlternateHrefLangs when content.language is undefined [Alin Voinea - [`0305bf2`](https://github.com/eea/volto-eea-website-theme/commit/0305bf2f0ba9f3e0167b4a798a40b81804a7b71f)]
|
|
12
|
+
|
|
13
|
+
### [4.0.2](https://github.com/eea/volto-eea-website-theme/compare/4.0.1...4.0.2) - 8 April 2026
|
|
14
|
+
|
|
7
15
|
### [4.0.1](https://github.com/eea/volto-eea-website-theme/compare/4.0.0...4.0.1) - 8 April 2026
|
|
8
16
|
|
|
9
17
|
#### :hammer_and_wrench: Others
|
|
10
18
|
|
|
11
19
|
- Add eslint-disable [Miu Razvan - [`4566fb4`](https://github.com/eea/volto-eea-website-theme/commit/4566fb419fe531ff1dc077859e217e01164313ae)]
|
|
12
|
-
- Import routes from @root instead of @plone/volto [Miu Razvan - [`bc239e7`](https://github.com/eea/volto-eea-website-theme/commit/bc239e7a94b5b66c33ab2f6d1321fb7ebc5348ce)]
|
|
13
20
|
## [4.0.0](https://github.com/eea/volto-eea-website-theme/compare/3.19.1...4.0.0) - 7 April 2026
|
|
14
21
|
|
|
15
22
|
#### :rocket: New Features
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
2
|
-
import { GET_NAVIGATION_SETTINGS } from '
|
|
2
|
+
import { GET_NAVIGATION_SETTINGS } from '@eeacms/volto-eea-website-theme/constants/ActionTypes';
|
|
3
3
|
|
|
4
4
|
export const getNavigationSettings = (url = '') => {
|
|
5
5
|
let cleanedUrl = typeof url === 'string' ? url : '';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getNavigationSettings } from './navigation';
|
|
2
|
-
import { GET_NAVIGATION_SETTINGS } from '
|
|
2
|
+
import { GET_NAVIGATION_SETTINGS } from '@eeacms/volto-eea-website-theme/constants/ActionTypes';
|
|
3
3
|
|
|
4
4
|
jest.mock('@plone/volto/helpers', () => ({
|
|
5
5
|
flattenToAppURL: jest.fn((url) => {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PATCH from Volto 18.33.0
|
|
3
|
+
* To be removed when issue is fixed and released:
|
|
4
|
+
* https://github.com/plone/volto/issues/7309
|
|
5
|
+
* https://github.com/plone/volto/pull/8093
|
|
6
|
+
* https://github.com/plone/volto/pull/8094
|
|
7
|
+
* */
|
|
8
|
+
import config from '@plone/volto/registry';
|
|
9
|
+
import Helmet from '@plone/volto/helpers/Helmet/Helmet';
|
|
10
|
+
import { flattenToAppURL, toPublicURL } from '@plone/volto/helpers/Url/Url';
|
|
11
|
+
|
|
12
|
+
const AlternateHrefLangs = (props) => {
|
|
13
|
+
const { content } = props;
|
|
14
|
+
return (
|
|
15
|
+
<Helmet>
|
|
16
|
+
{config.settings.isMultilingual &&
|
|
17
|
+
content['@components']?.translations?.items &&
|
|
18
|
+
content.language?.token &&
|
|
19
|
+
[
|
|
20
|
+
...content['@components']?.translations?.items,
|
|
21
|
+
{ '@id': content['@id'], language: content.language.token },
|
|
22
|
+
].map((item, key) => {
|
|
23
|
+
return (
|
|
24
|
+
<link
|
|
25
|
+
key={key}
|
|
26
|
+
rel="alternate"
|
|
27
|
+
hrefLang={item.language}
|
|
28
|
+
href={toPublicURL(flattenToAppURL(item['@id']))}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
})}
|
|
32
|
+
</Helmet>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { AlternateHrefLangs };
|
package/src/customizations/volto/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
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
|
+
|
|
39
|
+
it('multilingual site, content without language field, renders nothing', () => {
|
|
40
|
+
config.settings.publicURL = 'https://plone.org';
|
|
41
|
+
config.settings.supportedLanguages = ['en', 'es'];
|
|
42
|
+
|
|
43
|
+
const content = {
|
|
44
|
+
'@id': 'http://localhost:8080/Plone/en/newsroom/news',
|
|
45
|
+
'@components': {
|
|
46
|
+
translations: {
|
|
47
|
+
items: [{ '@id': 'http://localhost:8080/Plone/es', language: 'es' }],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const store = mockStore({
|
|
53
|
+
intl: {
|
|
54
|
+
locale: 'en',
|
|
55
|
+
messages: {},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
renderer.create(
|
|
60
|
+
<Provider store={store}>
|
|
61
|
+
<AlternateHrefLangs content={content} />
|
|
62
|
+
</Provider>,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
66
|
+
expect(helmetLinks.length).toBe(0);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('multilingual site, with some translations', () => {
|
|
70
|
+
config.settings.publicURL = 'https://plone.org';
|
|
71
|
+
config.settings.isMultilingual = true;
|
|
72
|
+
config.settings.supportedLanguages = ['en', 'es', 'eu'];
|
|
73
|
+
|
|
74
|
+
const content = {
|
|
75
|
+
'@id': 'http://localhost:8080/Plone/en',
|
|
76
|
+
language: { token: 'en', title: 'English' },
|
|
77
|
+
'@components': {
|
|
78
|
+
translations: {
|
|
79
|
+
items: [{ '@id': 'http://localhost:8080/Plone/es', language: 'es' }],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const store = mockStore({
|
|
85
|
+
intl: {
|
|
86
|
+
locale: 'en',
|
|
87
|
+
messages: {},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// We need to force the component rendering
|
|
92
|
+
// to fill the Helmet
|
|
93
|
+
renderer.create(
|
|
94
|
+
<Provider store={store}>
|
|
95
|
+
<>
|
|
96
|
+
<AlternateHrefLangs content={content} />
|
|
97
|
+
</>
|
|
98
|
+
</Provider>,
|
|
99
|
+
);
|
|
100
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
101
|
+
|
|
102
|
+
expect(helmetLinks.length).toBe(2);
|
|
103
|
+
|
|
104
|
+
expect(helmetLinks).toContainEqual({
|
|
105
|
+
rel: 'alternate',
|
|
106
|
+
href: 'https://plone.org/es',
|
|
107
|
+
hrefLang: 'es',
|
|
108
|
+
});
|
|
109
|
+
expect(helmetLinks).toContainEqual({
|
|
110
|
+
rel: 'alternate',
|
|
111
|
+
href: 'https://plone.org/en',
|
|
112
|
+
hrefLang: 'en',
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('multilingual site, with all available translations', () => {
|
|
117
|
+
config.settings.publicURL = 'https://plone.org';
|
|
118
|
+
config.settings.isMultilingual = true;
|
|
119
|
+
config.settings.supportedLanguages = ['en', 'es', 'eu'];
|
|
120
|
+
const store = mockStore({
|
|
121
|
+
intl: {
|
|
122
|
+
locale: 'en',
|
|
123
|
+
messages: {},
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const content = {
|
|
128
|
+
'@id': 'http://localhost:8080/Plone/en',
|
|
129
|
+
language: { token: 'en', title: 'English' },
|
|
130
|
+
'@components': {
|
|
131
|
+
translations: {
|
|
132
|
+
items: [
|
|
133
|
+
{ '@id': 'http://localhost:8080/Plone/eu', language: 'eu' },
|
|
134
|
+
{ '@id': 'http://localhost:8080/Plone/es', language: 'es' },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// We need to force the component rendering
|
|
141
|
+
// to fill the Helmet
|
|
142
|
+
renderer.create(
|
|
143
|
+
<Provider store={store}>
|
|
144
|
+
<AlternateHrefLangs content={content} />
|
|
145
|
+
</Provider>,
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
149
|
+
|
|
150
|
+
// We expect having 3 links
|
|
151
|
+
expect(helmetLinks.length).toBe(3);
|
|
152
|
+
|
|
153
|
+
expect(helmetLinks).toContainEqual({
|
|
154
|
+
rel: 'alternate',
|
|
155
|
+
href: 'https://plone.org/eu',
|
|
156
|
+
hrefLang: 'eu',
|
|
157
|
+
});
|
|
158
|
+
expect(helmetLinks).toContainEqual({
|
|
159
|
+
rel: 'alternate',
|
|
160
|
+
href: 'https://plone.org/es',
|
|
161
|
+
hrefLang: 'es',
|
|
162
|
+
});
|
|
163
|
+
expect(helmetLinks).toContainEqual({
|
|
164
|
+
rel: 'alternate',
|
|
165
|
+
href: 'https://plone.org/en',
|
|
166
|
+
hrefLang: 'en',
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('multilingual site, with all available translations - with server URL', () => {
|
|
171
|
+
config.settings.publicURL = 'https://plone.org';
|
|
172
|
+
config.settings.isMultilingual = true;
|
|
173
|
+
config.settings.supportedLanguages = ['en', 'es', 'eu'];
|
|
174
|
+
const store = mockStore({
|
|
175
|
+
intl: {
|
|
176
|
+
locale: 'en',
|
|
177
|
+
messages: {},
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const content = {
|
|
182
|
+
'@id': 'http://localhost:8080/Plone/en',
|
|
183
|
+
language: { token: 'en', title: 'English' },
|
|
184
|
+
'@components': {
|
|
185
|
+
translations: {
|
|
186
|
+
items: [
|
|
187
|
+
{ '@id': 'http://localhost:8080/Plone/eu', language: 'eu' },
|
|
188
|
+
{ '@id': 'http://localhost:8080/Plone/es', language: 'es' },
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// We need to force the component rendering
|
|
195
|
+
// to fill the Helmet
|
|
196
|
+
renderer.create(
|
|
197
|
+
<Provider store={store}>
|
|
198
|
+
<AlternateHrefLangs content={content} />
|
|
199
|
+
</Provider>,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
const helmetLinks = Helmet.peek().linkTags;
|
|
203
|
+
|
|
204
|
+
// We expect having 3 links
|
|
205
|
+
expect(helmetLinks.length).toBe(3);
|
|
206
|
+
|
|
207
|
+
expect(helmetLinks).toContainEqual({
|
|
208
|
+
rel: 'alternate',
|
|
209
|
+
href: 'https://plone.org/eu',
|
|
210
|
+
hrefLang: 'eu',
|
|
211
|
+
});
|
|
212
|
+
expect(helmetLinks).toContainEqual({
|
|
213
|
+
rel: 'alternate',
|
|
214
|
+
href: 'https://plone.org/es',
|
|
215
|
+
hrefLang: 'es',
|
|
216
|
+
});
|
|
217
|
+
expect(helmetLinks).toContainEqual({
|
|
218
|
+
rel: 'alternate',
|
|
219
|
+
href: 'https://plone.org/en',
|
|
220
|
+
hrefLang: 'en',
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
});
|
|
@@ -21,9 +21,9 @@ import crypto from 'crypto';
|
|
|
21
21
|
import routes from '@root/routes';
|
|
22
22
|
import config from '@plone/volto/registry';
|
|
23
23
|
|
|
24
|
-
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
25
24
|
import Html from '@plone/volto/helpers/Html/Html';
|
|
26
25
|
import Api from '@plone/volto/helpers/Api/Api';
|
|
26
|
+
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
27
27
|
import { persistAuthToken } from '@plone/volto/helpers/AuthToken/AuthToken';
|
|
28
28
|
import {
|
|
29
29
|
toBackendLang,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import navigationReducer from './navigation';
|
|
2
|
-
import { GET_NAVIGATION_SETTINGS } from '
|
|
2
|
+
import { GET_NAVIGATION_SETTINGS } from '@eeacms/volto-eea-website-theme/constants/ActionTypes';
|
|
3
3
|
|
|
4
4
|
describe('navigation reducer', () => {
|
|
5
5
|
const initialState = {
|