@plone/volto 18.0.0-alpha.4 → 18.0.0-alpha.5
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/.eslintignore +1 -0
- package/.release-it.json +1 -0
- package/CHANGELOG.md +21 -0
- package/package.json +6 -3
- package/src/components/manage/Add/Add.jsx +6 -0
- package/src/components/manage/BlockChooser/BlockChooser.jsx +3 -1
- package/src/components/manage/BlockChooser/BlockChooserButton.jsx +5 -0
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +4 -0
- package/src/components/manage/Blocks/Block/DefaultEdit.jsx +3 -1
- package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +5 -0
- package/src/components/manage/Blocks/Block/Settings.jsx +10 -1
- package/src/components/manage/Blocks/Container/Data.jsx +4 -1
- package/src/components/manage/Blocks/HeroImageLeft/Data.jsx +3 -1
- package/src/components/manage/Blocks/Image/ImageSidebar.jsx +4 -1
- package/src/components/manage/Blocks/Listing/ListingData.jsx +4 -1
- package/src/components/manage/Blocks/Maps/MapsSidebar.jsx +3 -1
- package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +4 -0
- package/src/components/manage/Blocks/Teaser/Data.jsx +4 -1
- package/src/components/manage/Blocks/ToC/Edit.jsx +2 -0
- package/src/components/manage/Blocks/Video/VideoSidebar.jsx +3 -1
- package/src/components/manage/Edit/Edit.jsx +1 -0
- package/src/components/manage/Form/Form.jsx +9 -1
- package/src/components/theme/Image/Image.jsx +4 -2
- package/src/components/theme/Image/Image.test.jsx +32 -0
- package/src/helpers/Blocks/Blocks.js +11 -2
- package/src/helpers/Extensions/withBlockSchemaEnhancer.js +20 -9
- package/src/helpers/Url/Url.js +5 -4
- package/src/helpers/Url/Url.test.js +52 -0
- package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +3 -1
package/.eslintignore
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
types/
|
package/.release-it.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -17,6 +17,27 @@ myst:
|
|
|
17
17
|
|
|
18
18
|
<!-- towncrier release notes start -->
|
|
19
19
|
|
|
20
|
+
## 18.0.0-alpha.5 (2023-12-13)
|
|
21
|
+
|
|
22
|
+
### Feature
|
|
23
|
+
|
|
24
|
+
- Added conditional variations support. @sneridagh @robgietema [#5424](https://github.com/plone/volto/issues/5424)
|
|
25
|
+
- Added `navRoot` and `contentType` to `restricted` key in blocks configuration. @sneridagh [#5517](https://github.com/plone/volto/issues/5517)
|
|
26
|
+
- Add support for `preview_image_link` behavior in Volto Image component @sneridagh [#5523](https://github.com/plone/volto/issues/5523)
|
|
27
|
+
|
|
28
|
+
### Internal
|
|
29
|
+
|
|
30
|
+
- Add missing dependency on jsdom @sneridagh [#5490](https://github.com/plone/volto/issues/5490)
|
|
31
|
+
- Fix cypress artifacts path in acceptance tests. @davisagli [#5498](https://github.com/plone/volto/issues/5498)
|
|
32
|
+
- Make sure that the dependencies are built and available on all processes @sneridagh [#5514](https://github.com/plone/volto/issues/5514)
|
|
33
|
+
|
|
34
|
+
### Documentation
|
|
35
|
+
|
|
36
|
+
- Less comment blocks must have `*` as the first character on the second and subsequent lines, else the Pygments lexer fails. @stevepiercy [#5500](https://github.com/plone/volto/issues/5500)
|
|
37
|
+
- Revert #5500. See #5499 for actual cause of Pygments failure. @stevepiercy [#5504](https://github.com/plone/volto/issues/5504)
|
|
38
|
+
- Clarified where to run Make commands for building documentation. @stevepiercy [#5505](https://github.com/plone/volto/issues/5505)
|
|
39
|
+
- Changed installation of Vale from manual to automatic via `make docs-vale`. @stevepiercy [#5508](https://github.com/plone/volto/issues/5508)
|
|
40
|
+
|
|
20
41
|
## 18.0.0-alpha.4 (2023-12-02)
|
|
21
42
|
|
|
22
43
|
### Feature
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
}
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"version": "18.0.0-alpha.
|
|
12
|
+
"version": "18.0.0-alpha.5",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git@github.com:plone/volto.git"
|
|
@@ -312,9 +312,9 @@
|
|
|
312
312
|
"webpack-node-externals": "3.0.0",
|
|
313
313
|
"xmlrpc": "1.3.2",
|
|
314
314
|
"yarnhook": "0.5.1",
|
|
315
|
-
"@plone/registry": "1.0
|
|
315
|
+
"@plone/registry": "1.1.0",
|
|
316
316
|
"@plone/scripts": "3.1.0",
|
|
317
|
-
"@plone/volto-slate": "18.0.0-alpha.
|
|
317
|
+
"@plone/volto-slate": "18.0.0-alpha.5"
|
|
318
318
|
},
|
|
319
319
|
"devDependencies": {
|
|
320
320
|
"@jest/globals": "^29.7.0",
|
|
@@ -344,6 +344,7 @@
|
|
|
344
344
|
"identity-obj-proxy": "3.0.0",
|
|
345
345
|
"jest": "26.6.3",
|
|
346
346
|
"jest-environment-jsdom": "^26",
|
|
347
|
+
"jsdom": "^16.7.0",
|
|
347
348
|
"jsonwebtoken": "9.0.0",
|
|
348
349
|
"react-error-overlay": "6.0.9",
|
|
349
350
|
"react-is": "^16.13.1",
|
|
@@ -374,11 +375,13 @@
|
|
|
374
375
|
"start:prod": "NODE_ENV=production node build/server.js",
|
|
375
376
|
"prettier": "./node_modules/.bin/prettier --single-quote --check '{src,cypress}/**/*.{js,jsx,ts,tsx}' --check '*.js'",
|
|
376
377
|
"prettier:fix": "./node_modules/.bin/prettier --single-quote --write '{src,cypress}/**/*.{js,jsx,ts,tsx}' --write '*.js'",
|
|
378
|
+
"prettier:husky": "prettier --single-quote --write",
|
|
377
379
|
"stylelint": "./node_modules/.bin/stylelint 'theme/**/*.{css,less}' 'src/**/*.{css,less}'",
|
|
378
380
|
"stylelint:overrides": "./node_modules/.bin/stylelint 'theme/**/*.overrides' 'src/**/*.overrides'",
|
|
379
381
|
"stylelint:fix": "yarn stylelint --fix && yarn stylelint:overrides --fix",
|
|
380
382
|
"lint": "./node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx,ts,tsx,json}'",
|
|
381
383
|
"lint:fix": "./node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx,ts,tsx,json}'",
|
|
384
|
+
"lint:husky": "eslint --max-warnings=0 --fix",
|
|
382
385
|
"i18n": "rm -rf build/messages && NODE_ENV=production i18n",
|
|
383
386
|
"i18n:ci": "pnpm i18n && git diff -G'^[^\"POT]' --exit-code",
|
|
384
387
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
@@ -315,6 +315,9 @@ class Add extends Component {
|
|
|
315
315
|
<Form
|
|
316
316
|
ref={this.form}
|
|
317
317
|
key="translated-or-new-content-form"
|
|
318
|
+
navRoot={
|
|
319
|
+
this.props.content?.['@components']?.navroot?.navroot || {}
|
|
320
|
+
}
|
|
318
321
|
schema={this.props.schema}
|
|
319
322
|
type={this.props.type}
|
|
320
323
|
formData={{
|
|
@@ -334,6 +337,9 @@ class Add extends Component {
|
|
|
334
337
|
// Copy the Language Independent Fields values from the to-be translated content
|
|
335
338
|
// into the default values of the translated content Add form.
|
|
336
339
|
...lifData(),
|
|
340
|
+
parent: {
|
|
341
|
+
'@id': this.props.content?.['@id'] || '',
|
|
342
|
+
},
|
|
337
343
|
}}
|
|
338
344
|
requestError={this.state.error}
|
|
339
345
|
onSubmit={this.onSubmit}
|
|
@@ -31,6 +31,8 @@ const BlockChooser = ({
|
|
|
31
31
|
blocksConfig = config.blocks.blocksConfig,
|
|
32
32
|
blockChooserRef,
|
|
33
33
|
properties = {},
|
|
34
|
+
navRoot,
|
|
35
|
+
contentType,
|
|
34
36
|
}) => {
|
|
35
37
|
const intl = useIntl();
|
|
36
38
|
const hasAllowedBlocks = !isEmpty(allowedBlocks);
|
|
@@ -55,7 +57,7 @@ const BlockChooser = ({
|
|
|
55
57
|
// depending on this function, given properties (current present blocks) and the
|
|
56
58
|
// block being evaluated
|
|
57
59
|
return typeof item.restricted === 'function'
|
|
58
|
-
? !item.restricted({ properties, block: item })
|
|
60
|
+
? !item.restricted({ properties, block: item, navRoot, contentType })
|
|
59
61
|
: !item.restricted;
|
|
60
62
|
}
|
|
61
63
|
}
|
|
@@ -54,7 +54,10 @@ const BlockChooserButton = (props) => {
|
|
|
54
54
|
blocksConfig,
|
|
55
55
|
buttonComponent,
|
|
56
56
|
properties,
|
|
57
|
+
navRoot,
|
|
58
|
+
contentType,
|
|
57
59
|
} = props;
|
|
60
|
+
|
|
58
61
|
const { disableNewBlocks } = data;
|
|
59
62
|
const [addNewBlockOpened, setAddNewBlockOpened] = React.useState(false);
|
|
60
63
|
|
|
@@ -142,6 +145,8 @@ const BlockChooserButton = (props) => {
|
|
|
142
145
|
properties={properties}
|
|
143
146
|
showRestricted={showRestricted}
|
|
144
147
|
ref={blockChooserRef}
|
|
148
|
+
navRoot={navRoot}
|
|
149
|
+
contentType={contentType}
|
|
145
150
|
/>
|
|
146
151
|
</div>
|
|
147
152
|
</Portal>
|
|
@@ -28,6 +28,8 @@ const BlocksForm = (props) => {
|
|
|
28
28
|
pathname,
|
|
29
29
|
onChangeField,
|
|
30
30
|
properties,
|
|
31
|
+
type,
|
|
32
|
+
navRoot,
|
|
31
33
|
onChangeFormData,
|
|
32
34
|
selectedBlock,
|
|
33
35
|
multiSelected,
|
|
@@ -260,6 +262,8 @@ const BlocksForm = (props) => {
|
|
|
260
262
|
pathname,
|
|
261
263
|
metadata,
|
|
262
264
|
properties,
|
|
265
|
+
contentType: type,
|
|
266
|
+
navRoot,
|
|
263
267
|
blocksConfig,
|
|
264
268
|
selected: selectedBlock === childId,
|
|
265
269
|
multiSelected: multiSelected?.includes(childId),
|
|
@@ -7,7 +7,7 @@ import DefaultBlockView from './DefaultView';
|
|
|
7
7
|
|
|
8
8
|
const DefaultBlockEdit = (props) => {
|
|
9
9
|
const { blocksConfig = config.blocks.blocksConfig } = props;
|
|
10
|
-
const { data, onChangeBlock, block, selected } = props;
|
|
10
|
+
const { data, onChangeBlock, block, selected, navRoot, contentType } = props;
|
|
11
11
|
const intl = useIntl();
|
|
12
12
|
const blockSchema = blocksConfig?.[data['@type']]?.blockSchema;
|
|
13
13
|
const schema =
|
|
@@ -32,6 +32,8 @@ const DefaultBlockEdit = (props) => {
|
|
|
32
32
|
});
|
|
33
33
|
}}
|
|
34
34
|
formData={data}
|
|
35
|
+
navRoot={navRoot}
|
|
36
|
+
contentType={contentType}
|
|
35
37
|
/>
|
|
36
38
|
</SidebarPortal>
|
|
37
39
|
) : (
|
|
@@ -47,7 +47,10 @@ const EditBlockWrapper = (props) => {
|
|
|
47
47
|
editable,
|
|
48
48
|
properties,
|
|
49
49
|
showBlockChooser,
|
|
50
|
+
navRoot,
|
|
51
|
+
contentType,
|
|
50
52
|
} = blockProps;
|
|
53
|
+
|
|
51
54
|
const visible = selected && !hideHandler(data);
|
|
52
55
|
|
|
53
56
|
const required = isBoolean(data.required)
|
|
@@ -107,6 +110,8 @@ const EditBlockWrapper = (props) => {
|
|
|
107
110
|
blocksConfig={blocksConfig}
|
|
108
111
|
size="24px"
|
|
109
112
|
properties={properties}
|
|
113
|
+
navRoot={navRoot}
|
|
114
|
+
contentType={contentType}
|
|
110
115
|
/>
|
|
111
116
|
)}
|
|
112
117
|
</div>
|
|
@@ -3,7 +3,14 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { injectIntl } from 'react-intl';
|
|
4
4
|
import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
|
|
5
5
|
|
|
6
|
-
const Settings = ({
|
|
6
|
+
const Settings = ({
|
|
7
|
+
data,
|
|
8
|
+
block,
|
|
9
|
+
onChangeBlock,
|
|
10
|
+
schema,
|
|
11
|
+
navRoot,
|
|
12
|
+
contentType,
|
|
13
|
+
}) => {
|
|
7
14
|
return (
|
|
8
15
|
<BlockDataForm
|
|
9
16
|
schema={schema}
|
|
@@ -17,6 +24,8 @@ const Settings = ({ data, block, onChangeBlock, schema }) => {
|
|
|
17
24
|
onChangeBlock={onChangeBlock}
|
|
18
25
|
formData={data}
|
|
19
26
|
applySchemaEnhancers={false}
|
|
27
|
+
navRoot={navRoot}
|
|
28
|
+
contentType={contentType}
|
|
20
29
|
/>
|
|
21
30
|
);
|
|
22
31
|
};
|
|
@@ -2,7 +2,8 @@ import { useIntl } from 'react-intl';
|
|
|
2
2
|
import { BlockDataForm } from '@plone/volto/components';
|
|
3
3
|
|
|
4
4
|
const ContainerData = (props) => {
|
|
5
|
-
const { block, blocksConfig, data, onChangeBlock } =
|
|
5
|
+
const { block, blocksConfig, data, onChangeBlock, navRoot, contentType } =
|
|
6
|
+
props;
|
|
6
7
|
const intl = useIntl();
|
|
7
8
|
|
|
8
9
|
const schema = blocksConfig[data['@type']].blockSchema({ intl });
|
|
@@ -25,6 +26,8 @@ const ContainerData = (props) => {
|
|
|
25
26
|
block={block}
|
|
26
27
|
onChangeBlock={onChangeBlock}
|
|
27
28
|
blocksConfig={blocksConfig}
|
|
29
|
+
navRoot={navRoot}
|
|
30
|
+
contentType={contentType}
|
|
28
31
|
/>
|
|
29
32
|
);
|
|
30
33
|
};
|
|
@@ -4,7 +4,7 @@ import schemaHero from './schema.js';
|
|
|
4
4
|
import { BlockDataForm } from '@plone/volto/components';
|
|
5
5
|
|
|
6
6
|
const HeroImageLeftBlockData = (props) => {
|
|
7
|
-
const { block, data, onChangeBlock } = props;
|
|
7
|
+
const { block, data, onChangeBlock, navRoot, contentType } = props;
|
|
8
8
|
const intl = useIntl();
|
|
9
9
|
const schema = schemaHero({ ...props, intl });
|
|
10
10
|
return (
|
|
@@ -20,6 +20,8 @@ const HeroImageLeftBlockData = (props) => {
|
|
|
20
20
|
onChangeBlock={onChangeBlock}
|
|
21
21
|
formData={data}
|
|
22
22
|
block={block}
|
|
23
|
+
navRoot={navRoot}
|
|
24
|
+
contentType={contentType}
|
|
23
25
|
/>
|
|
24
26
|
);
|
|
25
27
|
};
|
|
@@ -9,7 +9,8 @@ import imageSVG from '@plone/volto/icons/image.svg';
|
|
|
9
9
|
import trashSVG from '@plone/volto/icons/delete.svg';
|
|
10
10
|
|
|
11
11
|
const ImageSidebar = (props) => {
|
|
12
|
-
const { blocksConfig, data, block, onChangeBlock } =
|
|
12
|
+
const { blocksConfig, data, block, onChangeBlock, navRoot, contentType } =
|
|
13
|
+
props;
|
|
13
14
|
const intl = useIntl();
|
|
14
15
|
const schema = ImageSchema({ formData: data, intl });
|
|
15
16
|
return (
|
|
@@ -94,6 +95,8 @@ const ImageSidebar = (props) => {
|
|
|
94
95
|
formData={data}
|
|
95
96
|
block={block}
|
|
96
97
|
blocksConfig={blocksConfig}
|
|
98
|
+
navRoot={navRoot}
|
|
99
|
+
contentType={contentType}
|
|
97
100
|
/>
|
|
98
101
|
</>
|
|
99
102
|
);
|
|
@@ -4,7 +4,8 @@ import { useIntl } from 'react-intl';
|
|
|
4
4
|
import { BlockDataForm } from '@plone/volto/components';
|
|
5
5
|
|
|
6
6
|
const ListingData = (props) => {
|
|
7
|
-
const { data, block, blocksConfig, onChangeBlock } =
|
|
7
|
+
const { data, block, blocksConfig, onChangeBlock, navRoot, contentType } =
|
|
8
|
+
props;
|
|
8
9
|
const intl = useIntl();
|
|
9
10
|
const schema = blocksConfig.listing.blockSchema({
|
|
10
11
|
...props,
|
|
@@ -25,6 +26,8 @@ const ListingData = (props) => {
|
|
|
25
26
|
formData={data}
|
|
26
27
|
blocksConfig={blocksConfig}
|
|
27
28
|
block={block}
|
|
29
|
+
navRoot={navRoot}
|
|
30
|
+
contentType={contentType}
|
|
28
31
|
/>
|
|
29
32
|
);
|
|
30
33
|
};
|
|
@@ -18,7 +18,7 @@ const messages = defineMessages({
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const MapsSidebar = (props) => {
|
|
21
|
-
const { data, block, onChangeBlock } = props;
|
|
21
|
+
const { data, block, onChangeBlock, navRoot, contentType } = props;
|
|
22
22
|
const intl = useIntl();
|
|
23
23
|
const schema = MapsSchema({ ...props, intl });
|
|
24
24
|
|
|
@@ -42,6 +42,8 @@ const MapsSidebar = (props) => {
|
|
|
42
42
|
onChangeBlock={onChangeBlock}
|
|
43
43
|
formData={data}
|
|
44
44
|
block={block}
|
|
45
|
+
navRoot={navRoot}
|
|
46
|
+
contentType={contentType}
|
|
45
47
|
/>
|
|
46
48
|
)}
|
|
47
49
|
</>
|
|
@@ -26,6 +26,8 @@ const SearchBlockEdit = (props) => {
|
|
|
26
26
|
data,
|
|
27
27
|
selected,
|
|
28
28
|
intl,
|
|
29
|
+
navRoot,
|
|
30
|
+
contentType,
|
|
29
31
|
onTriggerSearch,
|
|
30
32
|
querystring = {},
|
|
31
33
|
} = props;
|
|
@@ -83,6 +85,8 @@ const SearchBlockEdit = (props) => {
|
|
|
83
85
|
}}
|
|
84
86
|
onChangeBlock={onChangeBlock}
|
|
85
87
|
formData={data}
|
|
88
|
+
navRoot={navRoot}
|
|
89
|
+
contentType={contentType}
|
|
86
90
|
/>
|
|
87
91
|
</SidebarPortal>
|
|
88
92
|
</>
|
|
@@ -14,7 +14,8 @@ const messages = defineMessages({
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
const TeaserData = (props) => {
|
|
17
|
-
const { block, blocksConfig, data, onChangeBlock } =
|
|
17
|
+
const { block, blocksConfig, data, onChangeBlock, navRoot, contentType } =
|
|
18
|
+
props;
|
|
18
19
|
const intl = useIntl();
|
|
19
20
|
|
|
20
21
|
const reset = () => {
|
|
@@ -64,6 +65,8 @@ const TeaserData = (props) => {
|
|
|
64
65
|
block={block}
|
|
65
66
|
blocksConfig={blocksConfig}
|
|
66
67
|
headerActions={HeaderActions}
|
|
68
|
+
navRoot={navRoot}
|
|
69
|
+
contentType={contentType}
|
|
67
70
|
/>
|
|
68
71
|
);
|
|
69
72
|
};
|
|
@@ -18,7 +18,7 @@ const messages = defineMessages({
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const VideoSidebar = (props) => {
|
|
21
|
-
const { data, block, onChangeBlock } = props;
|
|
21
|
+
const { data, block, onChangeBlock, navRoot, contentType } = props;
|
|
22
22
|
const intl = useIntl();
|
|
23
23
|
const schema = VideoBlockSchema({ ...props, intl });
|
|
24
24
|
|
|
@@ -42,6 +42,8 @@ const VideoSidebar = (props) => {
|
|
|
42
42
|
onChangeBlock={onChangeBlock}
|
|
43
43
|
formData={data}
|
|
44
44
|
block={block}
|
|
45
|
+
navRoot={navRoot}
|
|
46
|
+
contentType={contentType}
|
|
45
47
|
/>
|
|
46
48
|
)}
|
|
47
49
|
</>
|
|
@@ -286,6 +286,7 @@ class Edit extends Component {
|
|
|
286
286
|
<Form
|
|
287
287
|
isEditForm
|
|
288
288
|
ref={this.form}
|
|
289
|
+
navRoot={this.props.content?.['@components']?.navroot?.navroot || {}}
|
|
289
290
|
schema={this.props.schema}
|
|
290
291
|
type={this.props.content?.['@type']}
|
|
291
292
|
formData={this.props.content}
|
|
@@ -544,7 +544,13 @@ class Form extends Component {
|
|
|
544
544
|
*/
|
|
545
545
|
render() {
|
|
546
546
|
const { settings } = config;
|
|
547
|
-
const {
|
|
547
|
+
const {
|
|
548
|
+
schema: originalSchema,
|
|
549
|
+
onCancel,
|
|
550
|
+
onSubmit,
|
|
551
|
+
navRoot,
|
|
552
|
+
type,
|
|
553
|
+
} = this.props;
|
|
548
554
|
const { formData } = this.state;
|
|
549
555
|
const schema = this.removeBlocksLayoutFields(originalSchema);
|
|
550
556
|
const Container =
|
|
@@ -593,6 +599,8 @@ class Form extends Component {
|
|
|
593
599
|
onChangeField={this.onChangeField}
|
|
594
600
|
onSelectBlock={this.onSelectBlock}
|
|
595
601
|
properties={formData}
|
|
602
|
+
navRoot={navRoot}
|
|
603
|
+
type={type}
|
|
596
604
|
pathname={this.props.pathname}
|
|
597
605
|
selectedBlock={this.state.selected}
|
|
598
606
|
multiSelected={this.state.multiSelected}
|
|
@@ -45,8 +45,10 @@ export default function Image({
|
|
|
45
45
|
if (!image) return null;
|
|
46
46
|
|
|
47
47
|
const isSvg = image['content-type'] === 'image/svg+xml';
|
|
48
|
+
// In case `base_path` is present (`preview_image_link`) use it as base path
|
|
49
|
+
const basePath = image.base_path || item['@id'];
|
|
48
50
|
|
|
49
|
-
attrs.src = `${flattenToAppURL(
|
|
51
|
+
attrs.src = `${flattenToAppURL(basePath)}/${image.download}`;
|
|
50
52
|
attrs.width = image.width;
|
|
51
53
|
attrs.height = image.height;
|
|
52
54
|
attrs.className = cx(className, { responsive });
|
|
@@ -61,7 +63,7 @@ export default function Image({
|
|
|
61
63
|
attrs.srcSet = sortedScales
|
|
62
64
|
.map(
|
|
63
65
|
(scale) =>
|
|
64
|
-
`${flattenToAppURL(
|
|
66
|
+
`${flattenToAppURL(basePath)}/${scale.download} ${scale.width}w`,
|
|
65
67
|
)
|
|
66
68
|
.join(', ');
|
|
67
69
|
}
|
|
@@ -113,6 +113,38 @@ test('renders an image component from a catalog brain', () => {
|
|
|
113
113
|
expect(json).toMatchSnapshot();
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
+
test('renders an image component from a catalog brain using `preview_image_link`', () => {
|
|
117
|
+
const component = renderer.create(
|
|
118
|
+
<Image
|
|
119
|
+
item={{
|
|
120
|
+
'@id': 'http://localhost:3000/blog/blog-post',
|
|
121
|
+
image_field: 'preview_image_link',
|
|
122
|
+
image_scales: {
|
|
123
|
+
preview_image_link: [
|
|
124
|
+
{
|
|
125
|
+
base_path: '/image.png',
|
|
126
|
+
download: '@@images/image.png',
|
|
127
|
+
width: 400,
|
|
128
|
+
height: 400,
|
|
129
|
+
scales: {
|
|
130
|
+
preview: {
|
|
131
|
+
download: '@@images/image-400.png',
|
|
132
|
+
width: 400,
|
|
133
|
+
height: 400,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
}}
|
|
140
|
+
imageField="preview_image_link"
|
|
141
|
+
alt="alt text"
|
|
142
|
+
/>,
|
|
143
|
+
);
|
|
144
|
+
const json = component.toJSON();
|
|
145
|
+
expect(json).toMatchSnapshot();
|
|
146
|
+
});
|
|
147
|
+
|
|
116
148
|
test('renders an image component from a string src', () => {
|
|
117
149
|
const component = renderer.create(
|
|
118
150
|
<Image
|
|
@@ -517,7 +517,10 @@ export function applySchemaDefaults({ data = {}, schema, intl }) {
|
|
|
517
517
|
* @param {Object} params An object with data, intl and anything else
|
|
518
518
|
* @return {Object} Derived data, with the defaults extracted from the schema
|
|
519
519
|
*/
|
|
520
|
-
export function applyBlockDefaults(
|
|
520
|
+
export function applyBlockDefaults(
|
|
521
|
+
{ data, intl, navRoot, contentType, ...rest },
|
|
522
|
+
blocksConfig,
|
|
523
|
+
) {
|
|
521
524
|
// We pay attention to not break on a missing (invalid) block.
|
|
522
525
|
const block_type = data?.['@type'];
|
|
523
526
|
const { blockSchema } =
|
|
@@ -528,7 +531,13 @@ export function applyBlockDefaults({ data, intl, ...rest }, blocksConfig) {
|
|
|
528
531
|
typeof blockSchema === 'function'
|
|
529
532
|
? blockSchema({ data, intl, ...rest })
|
|
530
533
|
: blockSchema;
|
|
531
|
-
schema = applySchemaEnhancer({
|
|
534
|
+
schema = applySchemaEnhancer({
|
|
535
|
+
schema,
|
|
536
|
+
formData: data,
|
|
537
|
+
intl,
|
|
538
|
+
navRoot,
|
|
539
|
+
contentType,
|
|
540
|
+
});
|
|
532
541
|
|
|
533
542
|
return applySchemaDefaults({ data, schema, intl });
|
|
534
543
|
}
|
|
@@ -199,6 +199,8 @@ export const applySchemaEnhancer = ({
|
|
|
199
199
|
formData,
|
|
200
200
|
intl,
|
|
201
201
|
blocksConfig = config.blocks.blocksConfig,
|
|
202
|
+
navRoot,
|
|
203
|
+
contentType,
|
|
202
204
|
}) => {
|
|
203
205
|
let schema, schemaEnhancer;
|
|
204
206
|
|
|
@@ -215,6 +217,8 @@ export const applySchemaEnhancer = ({
|
|
|
215
217
|
schema: cloneDeepSchema(originalSchema),
|
|
216
218
|
formData,
|
|
217
219
|
intl,
|
|
220
|
+
navRoot,
|
|
221
|
+
contentType,
|
|
218
222
|
});
|
|
219
223
|
return schema || originalSchema;
|
|
220
224
|
}
|
|
@@ -230,12 +234,15 @@ export const applySchemaEnhancer = ({
|
|
|
230
234
|
schema: cloneDeepSchema(originalSchema),
|
|
231
235
|
formData,
|
|
232
236
|
intl,
|
|
237
|
+
navRoot,
|
|
238
|
+
contentType,
|
|
233
239
|
})
|
|
234
240
|
: cloneDeepSchema(originalSchema);
|
|
235
241
|
|
|
236
242
|
// Finalize the schema with a schemaEnhancer in the block config;
|
|
237
243
|
schemaEnhancer = blocksConfig?.[blockType]?.schemaEnhancer;
|
|
238
|
-
if (schemaEnhancer)
|
|
244
|
+
if (schemaEnhancer)
|
|
245
|
+
schema = schemaEnhancer({ schema, formData, intl, navRoot, contentType });
|
|
239
246
|
|
|
240
247
|
return schema || originalSchema;
|
|
241
248
|
};
|
|
@@ -248,7 +255,7 @@ export const applySchemaEnhancer = ({
|
|
|
248
255
|
* - adds the variation selection input (as a choice widget)
|
|
249
256
|
*/
|
|
250
257
|
export const withVariationSchemaEnhancer = (FormComponent) => (props) => {
|
|
251
|
-
const { formData, schema: originalSchema } = props;
|
|
258
|
+
const { formData, schema: originalSchema, navRoot, contentType } = props;
|
|
252
259
|
const intl = useIntl();
|
|
253
260
|
|
|
254
261
|
const blocksConfig = getBlocksConfig(props);
|
|
@@ -256,15 +263,10 @@ export const withVariationSchemaEnhancer = (FormComponent) => (props) => {
|
|
|
256
263
|
const blockType = formData['@type'];
|
|
257
264
|
const variations = blocksConfig[blockType]?.variations || [];
|
|
258
265
|
|
|
259
|
-
let schema =
|
|
260
|
-
schema: originalSchema,
|
|
261
|
-
formData,
|
|
262
|
-
intl,
|
|
263
|
-
blocksConfig,
|
|
264
|
-
});
|
|
266
|
+
let schema = cloneDeepSchema(originalSchema);
|
|
265
267
|
|
|
266
268
|
if (variations.length > 1) {
|
|
267
|
-
addExtensionFieldToSchema({
|
|
269
|
+
schema = addExtensionFieldToSchema({
|
|
268
270
|
schema,
|
|
269
271
|
name: 'variation',
|
|
270
272
|
items: variations,
|
|
@@ -274,6 +276,15 @@ export const withVariationSchemaEnhancer = (FormComponent) => (props) => {
|
|
|
274
276
|
});
|
|
275
277
|
}
|
|
276
278
|
|
|
279
|
+
schema = applySchemaEnhancer({
|
|
280
|
+
schema,
|
|
281
|
+
formData,
|
|
282
|
+
intl,
|
|
283
|
+
blocksConfig,
|
|
284
|
+
navRoot,
|
|
285
|
+
contentType,
|
|
286
|
+
});
|
|
287
|
+
|
|
277
288
|
return <FormComponent {...props} schema={schema} />;
|
|
278
289
|
};
|
|
279
290
|
|
package/src/helpers/Url/Url.js
CHANGED
|
@@ -366,19 +366,20 @@ export const URLUtils = {
|
|
|
366
366
|
* @returns {object} New object with the flattened scale URLs
|
|
367
367
|
*/
|
|
368
368
|
export function flattenScales(path, image) {
|
|
369
|
-
function removeObjectIdFromURL(
|
|
370
|
-
return scale.replace(`${
|
|
369
|
+
function removeObjectIdFromURL(basePath, scale) {
|
|
370
|
+
return scale.replace(`${basePath}/`, '');
|
|
371
371
|
}
|
|
372
372
|
if (!image) return;
|
|
373
373
|
|
|
374
|
+
const basePath = image.base_path || path;
|
|
374
375
|
const imageInfo = {
|
|
375
376
|
...image,
|
|
376
|
-
download: flattenToAppURL(removeObjectIdFromURL(
|
|
377
|
+
download: flattenToAppURL(removeObjectIdFromURL(basePath, image.download)),
|
|
377
378
|
};
|
|
378
379
|
|
|
379
380
|
Object.keys(imageInfo.scales).forEach((key) => {
|
|
380
381
|
imageInfo.scales[key].download = flattenToAppURL(
|
|
381
|
-
removeObjectIdFromURL(
|
|
382
|
+
removeObjectIdFromURL(basePath, image.scales[key].download),
|
|
382
383
|
);
|
|
383
384
|
});
|
|
384
385
|
|
|
@@ -351,6 +351,7 @@ describe('Url', () => {
|
|
|
351
351
|
);
|
|
352
352
|
});
|
|
353
353
|
});
|
|
354
|
+
|
|
354
355
|
describe('flattenScales', () => {
|
|
355
356
|
it('flattenScales image is not set', () => {
|
|
356
357
|
const id = '/halfdome2022-2.jpg';
|
|
@@ -405,6 +406,57 @@ describe('Url', () => {
|
|
|
405
406
|
width: 1182,
|
|
406
407
|
});
|
|
407
408
|
});
|
|
409
|
+
|
|
410
|
+
it('[preview_image_link] flattenScales test from the catalog', () => {
|
|
411
|
+
const id = '/halfdome2022-2.jpg';
|
|
412
|
+
const image = {
|
|
413
|
+
base_path: '/broccoli.jpg',
|
|
414
|
+
'content-type': 'image/jpeg',
|
|
415
|
+
download: '@@images/image-1182-cf763ae23c52340d8a17a7afdb26c8cb.jpeg',
|
|
416
|
+
filename: 'halfdome2022.jpg',
|
|
417
|
+
height: 665,
|
|
418
|
+
scales: {
|
|
419
|
+
great: {
|
|
420
|
+
download:
|
|
421
|
+
'@@images/image-1200-539ab119ebadc7d011798980a4a5e8d4.jpeg',
|
|
422
|
+
height: 665,
|
|
423
|
+
width: 1182,
|
|
424
|
+
},
|
|
425
|
+
huge: {
|
|
426
|
+
download:
|
|
427
|
+
'@@images/image-1600-188968febc677890c1b99d5339f9bef1.jpeg',
|
|
428
|
+
height: 665,
|
|
429
|
+
width: 1182,
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
size: 319364,
|
|
433
|
+
width: 1182,
|
|
434
|
+
};
|
|
435
|
+
expect(flattenScales(id, image)).toStrictEqual({
|
|
436
|
+
base_path: '/broccoli.jpg',
|
|
437
|
+
'content-type': 'image/jpeg',
|
|
438
|
+
download: '@@images/image-1182-cf763ae23c52340d8a17a7afdb26c8cb.jpeg',
|
|
439
|
+
filename: 'halfdome2022.jpg',
|
|
440
|
+
height: 665,
|
|
441
|
+
scales: {
|
|
442
|
+
great: {
|
|
443
|
+
download:
|
|
444
|
+
'@@images/image-1200-539ab119ebadc7d011798980a4a5e8d4.jpeg',
|
|
445
|
+
height: 665,
|
|
446
|
+
width: 1182,
|
|
447
|
+
},
|
|
448
|
+
huge: {
|
|
449
|
+
download:
|
|
450
|
+
'@@images/image-1600-188968febc677890c1b99d5339f9bef1.jpeg',
|
|
451
|
+
height: 665,
|
|
452
|
+
width: 1182,
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
size: 319364,
|
|
456
|
+
width: 1182,
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
|
|
408
460
|
it('flattenScales test from serialization', () => {
|
|
409
461
|
const id = 'http://localhost:3000/halfdome2022-2.jpg';
|
|
410
462
|
const image = {
|
|
@@ -21,11 +21,13 @@ export function addExtensionFieldToSchema({ schema, name, items, intl, title, de
|
|
|
21
21
|
export function withBlockSchemaEnhancer(FormComponent: any, extensionName?: string, insertFieldToOrder?: typeof _addField): ({ ...props }: {
|
|
22
22
|
[x: string]: any;
|
|
23
23
|
}) => JSX.Element;
|
|
24
|
-
export function applySchemaEnhancer({ schema: originalSchema, formData, intl, blocksConfig, }: {
|
|
24
|
+
export function applySchemaEnhancer({ schema: originalSchema, formData, intl, blocksConfig, navRoot, contentType, }: {
|
|
25
25
|
schema: any;
|
|
26
26
|
formData: any;
|
|
27
27
|
intl: any;
|
|
28
28
|
blocksConfig?: any;
|
|
29
|
+
navRoot: any;
|
|
30
|
+
contentType: any;
|
|
29
31
|
}): any;
|
|
30
32
|
export function withVariationSchemaEnhancer(FormComponent: any): (props: any) => JSX.Element;
|
|
31
33
|
export namespace EMPTY_STYLES_SCHEMA {
|