@plone/volto 16.0.0 → 16.1.0
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 +16 -4
- package/package.json +2 -1
- package/src/components/manage/Blocks/HeroImageLeft/Data.jsx +2 -1
- package/src/components/manage/Blocks/Image/ImageSidebar.jsx +1 -0
- package/src/components/manage/Blocks/Listing/ListingData.jsx +1 -0
- package/src/components/manage/Blocks/Maps/MapsSidebar.jsx +1 -0
- package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +1 -0
- package/src/components/manage/Blocks/ToC/Edit.jsx +1 -0
- package/src/components/manage/Blocks/Video/VideoSidebar.jsx +1 -1
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +2 -2
- package/src/components/manage/Widgets/ObjectListWidget.jsx +19 -2
- package/src/config/Style.jsx +9 -0
- package/src/config/index.js +2 -0
- package/src/helpers/Blocks/Blocks.js +37 -38
- package/src/helpers/Blocks/Blocks.test.js +64 -0
- package/test-setup-config.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 16.1.0 (2022-11-23)
|
|
4
|
+
|
|
5
|
+
### Feature
|
|
6
|
+
|
|
7
|
+
- Support for drilled down current state and updater function from schema in `ObjectListWidget`. This allows to sync the current object selected from the UI and the block settings and viceversa @sneridagh
|
|
8
|
+
- Allow custom style wrapper classnames via fieldname suffixes. Added `config.settings.styleClassNameConverters` to register new suffix converters @tiberiuichim
|
|
9
|
+
|
|
10
|
+
### Bugfix
|
|
11
|
+
|
|
12
|
+
- Fix jest moduleNameMapper for `@plone/volto/babel` @tiberiuichim
|
|
13
|
+
- Fix addons loader test @tiberiuichim
|
|
14
|
+
- Pass down `onChangeBlock` prop to all stock blocks in core @sneridagh
|
|
15
|
+
- Fix user search by full name in users control panel @reebalazs
|
|
16
|
+
|
|
3
17
|
## 16.0.0 (2022-11-22)
|
|
4
18
|
|
|
5
19
|
### Breaking
|
|
@@ -127,8 +141,6 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa
|
|
|
127
141
|
- Allow passing ariaHidden, id and style to an Icon's SVG @JeffersonBledsoe #3908
|
|
128
142
|
- All Fields now understand the `default` prop as a fallback value in case their data value is missing. As a convenience, the `defaultValue` is also used as a fallback, but this shouldn't proliferate. @tiberiuichim
|
|
129
143
|
- There is an experimental setting to move the button for adding a new block to show below any selected block, instead of only on the left of empty text blocks. Set `config.experimental.addBlockButton.enabled = true` to enable it. @davisagli
|
|
130
|
-
- Allow custom style wrapper classnames via fieldname suffixes. Added `config.settings.styleClassNameConverters` to register new suffix converters @tiberiuichim
|
|
131
|
-
- Support for drilled down current state and updater function from schema in `ObjectListWidget`. This allows to sync the current object selected from the UI and the block settings and viceversa @sneridagh
|
|
132
144
|
|
|
133
145
|
### Bugfix
|
|
134
146
|
|
|
@@ -257,7 +269,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa
|
|
|
257
269
|
- Fix image tag for Plone 5.2.x, use 5.2.9 for now @sneridagh
|
|
258
270
|
- Cover an additional edge case for defaults @tiberiuichim
|
|
259
271
|
- Fix issue when using list markdown when list is already active (volto-slate) @robgietema
|
|
260
|
-
- Fix translation spelling of toggle
|
|
272
|
+
- Fix translation spelling of toggle @iFlameing
|
|
261
273
|
- Fix keyboard accessibility issue of Clear button in Folder content view @iFlameing
|
|
262
274
|
|
|
263
275
|
### Internal
|
|
@@ -365,7 +377,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa
|
|
|
365
377
|
|
|
366
378
|
- Fix keyboard accessibility issue of Clear button in Folder content view @iFlameing
|
|
367
379
|
- Fix issue when using list markdown when list is already active (volto-slate) @robgietema
|
|
368
|
-
- Fix translation spelling of toggle
|
|
380
|
+
- Fix translation spelling of toggle @iFlameing
|
|
369
381
|
|
|
370
382
|
### Documentation
|
|
371
383
|
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
}
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"version": "16.
|
|
12
|
+
"version": "16.1.0",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git@github.com:plone/volto.git"
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
"moduleNameMapper": {
|
|
87
87
|
"@plone/volto/package.json": "<rootDir>/package.json",
|
|
88
|
+
"@plone/volto/babel": "<rootDir>/babel.js",
|
|
88
89
|
"@plone/volto/(.*)$": "<rootDir>/src/$1",
|
|
89
90
|
"@plone/volto-slate": "<rootDir>/packages/volto-slate/src",
|
|
90
91
|
"~/config": "<rootDir>/src/config",
|
|
@@ -9,7 +9,6 @@ const HeroImageLeftBlockData = (props) => {
|
|
|
9
9
|
const schema = schemaHero({ ...props, intl });
|
|
10
10
|
return (
|
|
11
11
|
<BlockDataForm
|
|
12
|
-
block={block}
|
|
13
12
|
schema={schema}
|
|
14
13
|
title={schema.title}
|
|
15
14
|
onChangeField={(id, value) => {
|
|
@@ -18,7 +17,9 @@ const HeroImageLeftBlockData = (props) => {
|
|
|
18
17
|
[id]: value,
|
|
19
18
|
});
|
|
20
19
|
}}
|
|
20
|
+
onChangeBlock={onChangeBlock}
|
|
21
21
|
formData={data}
|
|
22
|
+
block={block}
|
|
22
23
|
/>
|
|
23
24
|
);
|
|
24
25
|
};
|
|
@@ -140,7 +140,7 @@ class UsersControlpanel extends Component {
|
|
|
140
140
|
(this.props.createRequest.loading && nextProps.createRequest.loaded)
|
|
141
141
|
) {
|
|
142
142
|
this.props.listUsers({
|
|
143
|
-
|
|
143
|
+
search: this.state.search,
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
146
|
if (this.props.createRequest.loading && nextProps.createRequest.loaded) {
|
|
@@ -172,7 +172,7 @@ class UsersControlpanel extends Component {
|
|
|
172
172
|
onSearch(event) {
|
|
173
173
|
event.preventDefault();
|
|
174
174
|
this.props.listUsers({
|
|
175
|
-
|
|
175
|
+
search: this.state.search,
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -57,7 +57,9 @@ const messages = defineMessages({
|
|
|
57
57
|
* }
|
|
58
58
|
* mutated.fieldsets[0].fields.push('extraField');
|
|
59
59
|
* return mutated;
|
|
60
|
-
* }
|
|
60
|
+
* },
|
|
61
|
+
* activeObject: 0, // Current active object drilled down from the schema (if present)
|
|
62
|
+
* setActiveObject: () => {} // The current active object state updater function drilled down from the schema (if present)
|
|
61
63
|
* },
|
|
62
64
|
* ```
|
|
63
65
|
*/
|
|
@@ -71,7 +73,22 @@ const ObjectListWidget = (props) => {
|
|
|
71
73
|
onChange,
|
|
72
74
|
schemaExtender,
|
|
73
75
|
} = props;
|
|
74
|
-
const [
|
|
76
|
+
const [localActiveObject, setLocalActiveObject] = React.useState(
|
|
77
|
+
props.activeObject ?? value.length - 1,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
let activeObject, setActiveObject;
|
|
81
|
+
if (
|
|
82
|
+
(props.activeObject || props.activeObject === 0) &&
|
|
83
|
+
props.setActiveObject
|
|
84
|
+
) {
|
|
85
|
+
activeObject = props.activeObject;
|
|
86
|
+
setActiveObject = props.setActiveObject;
|
|
87
|
+
} else {
|
|
88
|
+
activeObject = localActiveObject;
|
|
89
|
+
setActiveObject = setLocalActiveObject;
|
|
90
|
+
}
|
|
91
|
+
|
|
75
92
|
const intl = useIntl();
|
|
76
93
|
|
|
77
94
|
function handleChangeActiveObject(e, blockProps) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const styleClassNameConverters = {
|
|
2
|
+
default: (name, value, prefix = '') => {
|
|
3
|
+
return value
|
|
4
|
+
? `has--${prefix}${name}--${(value || '').toString().replace(/^#/, '')}`
|
|
5
|
+
: null;
|
|
6
|
+
},
|
|
7
|
+
noprefix: (name, value) => value,
|
|
8
|
+
bool: (name, value) => (value ? name : ''),
|
|
9
|
+
};
|
package/src/config/index.js
CHANGED
|
@@ -24,6 +24,7 @@ import { loadables } from './Loadables';
|
|
|
24
24
|
import { workflowMapping } from './Workflows';
|
|
25
25
|
|
|
26
26
|
import { contentIcons } from './ContentIcons';
|
|
27
|
+
import { styleClassNameConverters } from './Style';
|
|
27
28
|
import {
|
|
28
29
|
controlPanelsIcons,
|
|
29
30
|
filterControlPanels,
|
|
@@ -167,6 +168,7 @@ let config = {
|
|
|
167
168
|
addonsInfo: addonsInfo,
|
|
168
169
|
workflowMapping,
|
|
169
170
|
errorHandlers: [], // callables for unhandled errors
|
|
171
|
+
styleClassNameConverters,
|
|
170
172
|
},
|
|
171
173
|
experimental: {
|
|
172
174
|
addBlockButton: {
|
|
@@ -3,16 +3,7 @@
|
|
|
3
3
|
* @module helpers/Blocks
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
omit,
|
|
8
|
-
without,
|
|
9
|
-
endsWith,
|
|
10
|
-
find,
|
|
11
|
-
isObject,
|
|
12
|
-
keys,
|
|
13
|
-
toPairs,
|
|
14
|
-
merge,
|
|
15
|
-
} from 'lodash';
|
|
6
|
+
import { omit, without, endsWith, find, isObject, keys, merge } from 'lodash';
|
|
16
7
|
import move from 'lodash-move';
|
|
17
8
|
import { v4 as uuid } from 'uuid';
|
|
18
9
|
import config from '@plone/volto/registry';
|
|
@@ -450,35 +441,43 @@ export function applyBlockDefaults({ data, intl, ...rest }, blocksConfig) {
|
|
|
450
441
|
return applySchemaDefaults({ data, schema, intl });
|
|
451
442
|
}
|
|
452
443
|
|
|
453
|
-
|
|
454
|
-
|
|
444
|
+
/**
|
|
445
|
+
* Converts a name+value style pair (ex: color/red) to a classname,
|
|
446
|
+
* such as "has--color--red"
|
|
447
|
+
*
|
|
448
|
+
* This can be expanded via the style names, by suffixing them with special
|
|
449
|
+
* converters. See config.settings.styleClassNameConverters. Examples:
|
|
450
|
+
*
|
|
451
|
+
* styleToClassName('theme:noprefix', 'primary') returns "primary"
|
|
452
|
+
* styleToClassName('inverted:bool', true) returns 'inverted'
|
|
453
|
+
* styleToClassName('inverted:bool', false) returns ''
|
|
454
|
+
*/
|
|
455
|
+
export const styleToClassName = (key, value, prefix = '') => {
|
|
456
|
+
const converters = config.settings.styleClassNameConverters;
|
|
457
|
+
const [name, ...convIds] = key.split(':');
|
|
458
|
+
|
|
459
|
+
return (convIds.length ? convIds : ['default'])
|
|
460
|
+
.map((id) => converters[id])
|
|
461
|
+
.reduce((acc, conv) => conv(acc, value, prefix), name);
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
export const buildStyleClassNamesFromData = (obj = {}, prefix = '') => {
|
|
465
|
+
// styles has the form:
|
|
455
466
|
// const styles = {
|
|
456
|
-
//
|
|
457
|
-
//
|
|
467
|
+
// color: 'red',
|
|
468
|
+
// backgroundColor: '#AABBCC',
|
|
458
469
|
// }
|
|
459
470
|
// Returns: ['has--color--red', 'has--backgroundColor--AABBCC']
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
});
|
|
473
|
-
return styleArray.map((item) => {
|
|
474
|
-
const classname = item.map((item) => {
|
|
475
|
-
const str_item = item ? item.toString() : '';
|
|
476
|
-
return str_item && str_item.startsWith('#')
|
|
477
|
-
? str_item.replace('#', '')
|
|
478
|
-
: str_item;
|
|
479
|
-
});
|
|
480
|
-
return `has--${classname[0]}--${classname[1]}${
|
|
481
|
-
classname[2] ? `--${classname[2]}` : ''
|
|
482
|
-
}`;
|
|
483
|
-
});
|
|
471
|
+
|
|
472
|
+
return Object.entries(obj)
|
|
473
|
+
.reduce(
|
|
474
|
+
(acc, [k, v]) => [
|
|
475
|
+
...acc,
|
|
476
|
+
...(isObject(v)
|
|
477
|
+
? buildStyleClassNamesFromData(v, `${prefix}${k}--`)
|
|
478
|
+
: [styleToClassName(k, v, prefix)]),
|
|
479
|
+
],
|
|
480
|
+
[],
|
|
481
|
+
)
|
|
482
|
+
.filter((v) => !!v);
|
|
484
483
|
};
|
|
@@ -819,6 +819,7 @@ describe('Blocks', () => {
|
|
|
819
819
|
expect(applyBlockDefaults({ data })).toEqual({});
|
|
820
820
|
});
|
|
821
821
|
});
|
|
822
|
+
|
|
822
823
|
describe('buildStyleClassNamesFromData', () => {
|
|
823
824
|
it('Sets styles classname array according to style values', () => {
|
|
824
825
|
const styles = {
|
|
@@ -830,6 +831,7 @@ describe('Blocks', () => {
|
|
|
830
831
|
'has--backgroundColor--AABBCC',
|
|
831
832
|
]);
|
|
832
833
|
});
|
|
834
|
+
|
|
833
835
|
it('Sets styles classname array according to style values with nested', () => {
|
|
834
836
|
const styles = {
|
|
835
837
|
color: 'red',
|
|
@@ -846,6 +848,7 @@ describe('Blocks', () => {
|
|
|
846
848
|
'has--nested--bar--black',
|
|
847
849
|
]);
|
|
848
850
|
});
|
|
851
|
+
|
|
849
852
|
it('Sets styles classname array according to style values with nested and colors', () => {
|
|
850
853
|
const styles = {
|
|
851
854
|
color: 'red',
|
|
@@ -863,6 +866,27 @@ describe('Blocks', () => {
|
|
|
863
866
|
]);
|
|
864
867
|
});
|
|
865
868
|
|
|
869
|
+
it('Supports multiple nested level', () => {
|
|
870
|
+
const styles = {
|
|
871
|
+
color: 'red',
|
|
872
|
+
backgroundColor: '#AABBCC',
|
|
873
|
+
nested: {
|
|
874
|
+
l1: 'white',
|
|
875
|
+
level2: {
|
|
876
|
+
foo: '#fff',
|
|
877
|
+
bar: '#000',
|
|
878
|
+
},
|
|
879
|
+
},
|
|
880
|
+
};
|
|
881
|
+
expect(buildStyleClassNamesFromData(styles)).toEqual([
|
|
882
|
+
'has--color--red',
|
|
883
|
+
'has--backgroundColor--AABBCC',
|
|
884
|
+
'has--nested--l1--white',
|
|
885
|
+
'has--nested--level2--foo--fff',
|
|
886
|
+
'has--nested--level2--bar--000',
|
|
887
|
+
]);
|
|
888
|
+
});
|
|
889
|
+
|
|
866
890
|
it('Sets styles classname array according to style values with int values', () => {
|
|
867
891
|
const styles = {
|
|
868
892
|
color: 'red',
|
|
@@ -873,5 +897,45 @@ describe('Blocks', () => {
|
|
|
873
897
|
'has--borderRadius--8',
|
|
874
898
|
]);
|
|
875
899
|
});
|
|
900
|
+
|
|
901
|
+
it('Understands noprefix converter for style values', () => {
|
|
902
|
+
const styles = {
|
|
903
|
+
color: 'red',
|
|
904
|
+
'theme:noprefix': 'primary',
|
|
905
|
+
};
|
|
906
|
+
expect(buildStyleClassNamesFromData(styles)).toEqual([
|
|
907
|
+
'has--color--red',
|
|
908
|
+
'primary',
|
|
909
|
+
]);
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
it('Understands bool converter for trueish value', () => {
|
|
913
|
+
const styles = {
|
|
914
|
+
color: 'red',
|
|
915
|
+
'inverted:bool': true,
|
|
916
|
+
};
|
|
917
|
+
expect(buildStyleClassNamesFromData(styles)).toEqual([
|
|
918
|
+
'has--color--red',
|
|
919
|
+
'inverted',
|
|
920
|
+
]);
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
it('Understands bool converter for false value', () => {
|
|
924
|
+
const styles = {
|
|
925
|
+
color: 'red',
|
|
926
|
+
'inverted:bool': false,
|
|
927
|
+
};
|
|
928
|
+
expect(buildStyleClassNamesFromData(styles)).toEqual(['has--color--red']);
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
it('Ugly edge cases', () => {
|
|
932
|
+
const styles = {
|
|
933
|
+
color: undefined,
|
|
934
|
+
nested: {
|
|
935
|
+
l1: {},
|
|
936
|
+
},
|
|
937
|
+
};
|
|
938
|
+
expect(buildStyleClassNamesFromData(styles)).toEqual([]);
|
|
939
|
+
});
|
|
876
940
|
});
|
|
877
941
|
});
|
package/test-setup-config.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from '@plone/volto/config/RichTextEditor/Blocks';
|
|
21
21
|
import FromHTMLCustomBlockFn from '@plone/volto/config/RichTextEditor/FromHTML';
|
|
22
22
|
import { contentIcons } from '@plone/volto/config/ContentIcons';
|
|
23
|
+
import { styleClassNameConverters } from '@plone/volto/config/Style';
|
|
23
24
|
|
|
24
25
|
import {
|
|
25
26
|
controlPanelsIcons,
|
|
@@ -74,6 +75,7 @@ config.set('settings', {
|
|
|
74
75
|
apiExpanders: [],
|
|
75
76
|
downloadableObjects: ['File'],
|
|
76
77
|
viewableInBrowserObjects: [],
|
|
78
|
+
styleClassNameConverters,
|
|
77
79
|
});
|
|
78
80
|
config.set('blocks', {
|
|
79
81
|
blocksConfig: {
|