@plone/volto 17.0.0-alpha.5 → 17.0.0-alpha.6
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 +26 -6
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +84 -13
- package/CONTRIBUTING.md +1 -1
- package/README.md +4 -4
- package/locales/de/LC_MESSAGES/volto.po +17 -17
- package/locales/de.json +1 -1
- package/package.json +3 -2
- package/packages/volto-slate/package.json +1 -1
- package/src/components/manage/Blocks/Listing/Edit.jsx +0 -14
- package/src/components/manage/Blocks/Listing/getAsyncData.js +10 -2
- package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +18 -13
- package/src/components/manage/Blocks/Search/SearchBlockView.jsx +2 -1
- package/src/components/manage/Contents/Contents.jsx +16 -14
- package/src/components/manage/Controlpanels/Controlpanels.jsx +190 -224
- package/src/components/manage/Controlpanels/Controlpanels.test.jsx +46 -7
- package/src/components/manage/Form/InlineForm.jsx +39 -9
- package/src/components/manage/Form/InlineFormState.js +8 -0
- package/src/components/manage/Widgets/ObjectListWidget.jsx +3 -8
- package/src/components/theme/Icon/Icon.jsx +2 -2
- package/src/components/theme/Login/Login.jsx +1 -0
- package/src/config/index.js +1 -0
- package/src/helpers/Robots/Robots.js +16 -1
- package/src/helpers/Url/Url.js +8 -3
- package/src/helpers/Url/Url.test.js +14 -0
- package/src/helpers/Utils/Utils.js +17 -4
- package/src/helpers/index.js +2 -0
- package/src/middleware/Api.test.js +54 -0
- package/src/middleware/api.js +1 -1
- package/test-setup-config.js +1 -0
- package/theme/themes/pastanaga/extras/sidebar.less +4 -0
package/src/config/index.js
CHANGED
|
@@ -28,9 +28,24 @@ export const generateRobots = (req) =>
|
|
|
28
28
|
if (error) {
|
|
29
29
|
resolve(text || error);
|
|
30
30
|
} else {
|
|
31
|
+
// It appears that express does not take the x-forwarded headers into
|
|
32
|
+
// consideration, so we do it ourselves.
|
|
33
|
+
const {
|
|
34
|
+
'x-forwarded-proto': forwardedProto,
|
|
35
|
+
'x-forwarded-host': forwardedHost,
|
|
36
|
+
'x-forwarded-port': forwardedPort,
|
|
37
|
+
} = req.headers;
|
|
38
|
+
const proto = forwardedProto ?? req.protocol;
|
|
39
|
+
const host = forwardedHost ?? req.get('Host');
|
|
40
|
+
const portNum = forwardedPort ?? req.get('Port');
|
|
41
|
+
const port =
|
|
42
|
+
(proto === 'https' && '' + portNum === '443') ||
|
|
43
|
+
(proto === 'http' && '' + portNum === '80')
|
|
44
|
+
? ''
|
|
45
|
+
: `:${portNum}`;
|
|
31
46
|
// Plone has probably returned the sitemap link with the internal url.
|
|
32
47
|
// If so, let's replace it with the current one.
|
|
33
|
-
const url = `${
|
|
48
|
+
const url = `${proto}://${host}${port}`;
|
|
34
49
|
text = text.replace(internalUrl, url);
|
|
35
50
|
// Replace the sitemap with the sitemap index.
|
|
36
51
|
text = text.replace('sitemap.xml.gz', 'sitemap-index.xml');
|
package/src/helpers/Url/Url.js
CHANGED
|
@@ -280,14 +280,14 @@ export function isTelephone(text) {
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
export function normaliseMail(email) {
|
|
283
|
-
if (email
|
|
283
|
+
if (email?.toLowerCase()?.startsWith('mailto:')) {
|
|
284
284
|
return email;
|
|
285
285
|
}
|
|
286
286
|
return `mailto:${email}`;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
export function normalizeTelephone(tel) {
|
|
290
|
-
if (tel
|
|
290
|
+
if (tel?.toLowerCase()?.startsWith('tel:')) {
|
|
291
291
|
return tel;
|
|
292
292
|
}
|
|
293
293
|
return `tel:${tel}`;
|
|
@@ -310,12 +310,17 @@ export function checkAndNormalizeUrl(url) {
|
|
|
310
310
|
res.url = URLUtils.normalizeTelephone(url);
|
|
311
311
|
} else {
|
|
312
312
|
//url
|
|
313
|
-
if (
|
|
313
|
+
if (
|
|
314
|
+
res.url?.length >= 0 &&
|
|
315
|
+
!res.url.startsWith('/') &&
|
|
316
|
+
!res.url.startsWith('#')
|
|
317
|
+
) {
|
|
314
318
|
res.url = URLUtils.normalizeUrl(url);
|
|
315
319
|
if (!URLUtils.isUrl(res.url)) {
|
|
316
320
|
res.isValid = false;
|
|
317
321
|
}
|
|
318
322
|
}
|
|
323
|
+
if (res.url === undefined || res.url === null) res.isValid = false;
|
|
319
324
|
}
|
|
320
325
|
return res;
|
|
321
326
|
}
|
|
@@ -14,6 +14,9 @@ import {
|
|
|
14
14
|
removeProtocol,
|
|
15
15
|
addAppURL,
|
|
16
16
|
expandToBackendURL,
|
|
17
|
+
checkAndNormalizeUrl,
|
|
18
|
+
normaliseMail,
|
|
19
|
+
normalizeTelephone,
|
|
17
20
|
} from './Url';
|
|
18
21
|
|
|
19
22
|
beforeEach(() => {
|
|
@@ -61,6 +64,17 @@ describe('Url', () => {
|
|
|
61
64
|
it('return empty string if no url is empty string', () => {
|
|
62
65
|
expect(getBaseUrl('')).toBe('');
|
|
63
66
|
});
|
|
67
|
+
it('return a null/undefined mailto adress ', () => {
|
|
68
|
+
expect(normaliseMail(null)).toBe('mailto:null');
|
|
69
|
+
expect(normaliseMail(undefined)).toBe('mailto:undefined');
|
|
70
|
+
});
|
|
71
|
+
it('return a null/undefined telephone number', () => {
|
|
72
|
+
expect(normalizeTelephone(null)).toBe('tel:null');
|
|
73
|
+
expect(normalizeTelephone(undefined)).toBe('tel:undefined');
|
|
74
|
+
});
|
|
75
|
+
it('null returns an invalid link', () => {
|
|
76
|
+
expect(checkAndNormalizeUrl(null).isValid).toBe(false);
|
|
77
|
+
});
|
|
64
78
|
});
|
|
65
79
|
|
|
66
80
|
describe('getView', () => {
|
|
@@ -258,11 +258,11 @@ export const removeFromArray = (array, index) => {
|
|
|
258
258
|
};
|
|
259
259
|
|
|
260
260
|
/**
|
|
261
|
-
*
|
|
261
|
+
* Moves an item from origin to target inside an array in an immutable way
|
|
262
262
|
* @param {Array} array Array with data
|
|
263
|
-
* @param {number} origin Index of item to be
|
|
264
|
-
* @param {number} target Index of item to be
|
|
265
|
-
* @returns {Array}
|
|
263
|
+
* @param {number} origin Index of item to be moved from
|
|
264
|
+
* @param {number} target Index of item to be moved to
|
|
265
|
+
* @returns {Array} Resultant array
|
|
266
266
|
*/
|
|
267
267
|
export const reorderArray = (array, origin, target) => {
|
|
268
268
|
const result = Array.from(array);
|
|
@@ -299,3 +299,16 @@ export const cloneDeepSchema = (object) => {
|
|
|
299
299
|
}
|
|
300
300
|
});
|
|
301
301
|
};
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Creates an array given a range of numbers
|
|
305
|
+
* @param {number} start start number from
|
|
306
|
+
* @param {number} stop stop number at
|
|
307
|
+
* @param {number} step step every each number in the sequence
|
|
308
|
+
* @returns {array} The result, eg. [0, 1, 2, 3, 4]
|
|
309
|
+
*/
|
|
310
|
+
export const arrayRange = (start, stop, step) =>
|
|
311
|
+
Array.from(
|
|
312
|
+
{ length: (stop - start) / step + 1 },
|
|
313
|
+
(value, index) => start + index * step,
|
|
314
|
+
);
|
package/src/helpers/index.js
CHANGED
|
@@ -53,6 +53,60 @@ describe('api middleware helpers', () => {
|
|
|
53
53
|
);
|
|
54
54
|
expect(result).toEqual('/de/mypage/@navigation?expand.navigation.depth=3');
|
|
55
55
|
});
|
|
56
|
+
it('addExpandersToPath - Path matching, preserve query', () => {
|
|
57
|
+
config.settings.apiExpanders = [
|
|
58
|
+
{
|
|
59
|
+
match: '/de/mypage',
|
|
60
|
+
GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'],
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
const result = addExpandersToPath(
|
|
65
|
+
'/de/mypage/@navigation?expand.navigation.depth=3',
|
|
66
|
+
GET_CONTENT,
|
|
67
|
+
);
|
|
68
|
+
expect(result).toEqual(
|
|
69
|
+
'/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3',
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
it('addExpandersToPath - Path matching, preserve query with multiple', () => {
|
|
73
|
+
config.settings.apiExpanders = [
|
|
74
|
+
{
|
|
75
|
+
match: '/de/mypage',
|
|
76
|
+
GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'],
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const result = addExpandersToPath(
|
|
81
|
+
'/de/mypage/@navigation?expand.navigation.depth=3&expand.other=2',
|
|
82
|
+
GET_CONTENT,
|
|
83
|
+
);
|
|
84
|
+
expect(result).toEqual(
|
|
85
|
+
'/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3&expand.other=2',
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
it('addExpandersToPath - Path not matching, preserve encoded query', () => {
|
|
89
|
+
config.settings.apiExpanders = [
|
|
90
|
+
{
|
|
91
|
+
match: '/de/otherpath',
|
|
92
|
+
GET_CONTENT: ['mycustomexpander'],
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
const result = addExpandersToPath('/de/mypage?query=a%26b', GET_CONTENT);
|
|
97
|
+
expect(result).toEqual('/de/mypage?query=a%26b');
|
|
98
|
+
});
|
|
99
|
+
it('addExpandersToPath - Path matching, preserve encoded query', () => {
|
|
100
|
+
config.settings.apiExpanders = [
|
|
101
|
+
{
|
|
102
|
+
match: '/de/mypage',
|
|
103
|
+
GET_CONTENT: ['mycustomexpander'],
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
const result = addExpandersToPath('/de/mypage?query=a%26b', GET_CONTENT);
|
|
108
|
+
expect(result).toEqual('/de/mypage?expand=mycustomexpander&query=a%26b');
|
|
109
|
+
});
|
|
56
110
|
it('addExpandersToPath - Two custom expanders from settings', () => {
|
|
57
111
|
config.settings.apiExpanders = [
|
|
58
112
|
{
|
package/src/middleware/api.js
CHANGED
|
@@ -43,7 +43,7 @@ export function addExpandersToPath(path, type, isAnonymous) {
|
|
|
43
43
|
const {
|
|
44
44
|
url,
|
|
45
45
|
query: { expand, ...query },
|
|
46
|
-
} = qs.parseUrl(path);
|
|
46
|
+
} = qs.parseUrl(path, { decode: false });
|
|
47
47
|
|
|
48
48
|
const expandersFromConfig = apiExpanders
|
|
49
49
|
.filter((expand) => matchPath(url, expand.match) && expand[type])
|
package/test-setup-config.js
CHANGED