@plone/volto 16.0.0 → 16.2.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 +30 -6
- package/cypress/support/commands.js +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +22 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +22 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +22 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +22 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +22 -0
- package/locales/eu.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +22 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +22 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +22 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +22 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +22 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +22 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +22 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +23 -1
- package/package.json +5 -3
- package/packages/volto-slate/README.md +2 -233
- package/packages/volto-slate/src/blocks/Text/extensions/index.js +1 -0
- package/packages/volto-slate/src/blocks/Text/extensions/normalizeExternalData.js +7 -0
- package/packages/volto-slate/src/blocks/Text/index.js +2 -0
- package/packages/volto-slate/src/editor/config.jsx +2 -0
- package/packages/volto-slate/src/editor/deserialize.js +25 -55
- package/packages/volto-slate/src/editor/extensions/index.js +1 -0
- package/packages/volto-slate/src/editor/extensions/insertData.js +17 -4
- package/packages/volto-slate/src/editor/extensions/normalizeExternalData.js +8 -0
- package/packages/volto-slate/src/editor/ui/Toolbar.jsx +8 -3
- package/packages/volto-slate/src/editor/ui/ToolbarButton.test.js +2 -2
- package/packages/volto-slate/src/editor/utils.js +248 -0
- package/src/components/index.js +3 -0
- package/src/components/manage/Blocks/Block/DefaultEdit.jsx +44 -0
- package/src/components/manage/Blocks/Block/DefaultView.jsx +78 -0
- package/src/components/manage/Blocks/Block/Edit.jsx +3 -2
- 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/Search/components/SelectFacet.jsx +2 -1
- 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 +14 -11
- package/src/components/manage/Widgets/NumberWidget.jsx +1 -1
- package/src/components/manage/Widgets/ObjectListWidget.jsx +19 -2
- package/src/components/theme/Error/ErrorBoundary.jsx +29 -0
- package/src/components/theme/Error/ErrorBoundary.test.jsx +34 -0
- package/src/components/theme/View/RenderBlocks.jsx +3 -1
- 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/src/helpers/MessageLabels/MessageLabels.js +18 -0
- package/test-setup-config.js +7 -0
|
@@ -3,6 +3,7 @@ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
|
3
3
|
import {
|
|
4
4
|
Option,
|
|
5
5
|
DropdownIndicator,
|
|
6
|
+
MultiValueContainer,
|
|
6
7
|
} from '@plone/volto/components/manage/Widgets/SelectStyling';
|
|
7
8
|
import { selectTheme, customSelectStyles } from './SelectStyling';
|
|
8
9
|
import {
|
|
@@ -32,7 +33,7 @@ const SelectFacet = (props) => {
|
|
|
32
33
|
options={choices}
|
|
33
34
|
styles={customSelectStyles}
|
|
34
35
|
theme={selectTheme}
|
|
35
|
-
components={{ DropdownIndicator, Option }}
|
|
36
|
+
components={{ DropdownIndicator, Option, MultiValueContainer }}
|
|
36
37
|
isDisabled={isEditMode}
|
|
37
38
|
onChange={(data) => {
|
|
38
39
|
if (data) {
|
|
@@ -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
|
|
|
@@ -439,23 +439,27 @@ class UsersControlpanel extends Component {
|
|
|
439
439
|
messages.addUserFormUsernameTitle,
|
|
440
440
|
),
|
|
441
441
|
type: 'string',
|
|
442
|
-
description:
|
|
443
|
-
|
|
442
|
+
description: this.props.intl.formatMessage(
|
|
443
|
+
messages.addUserFormUsernameDescription,
|
|
444
|
+
),
|
|
444
445
|
},
|
|
445
446
|
fullname: {
|
|
446
447
|
title: this.props.intl.formatMessage(
|
|
447
448
|
messages.addUserFormFullnameTitle,
|
|
448
449
|
),
|
|
449
450
|
type: 'string',
|
|
450
|
-
description:
|
|
451
|
+
description: this.props.intl.formatMessage(
|
|
452
|
+
messages.addUserFormFullnameDescription,
|
|
453
|
+
),
|
|
451
454
|
},
|
|
452
455
|
email: {
|
|
453
456
|
title: this.props.intl.formatMessage(
|
|
454
457
|
messages.addUserFormEmailTitle,
|
|
455
458
|
),
|
|
456
459
|
type: 'string',
|
|
457
|
-
description:
|
|
458
|
-
|
|
460
|
+
description: this.props.intl.formatMessage(
|
|
461
|
+
messages.addUserFormEmailDescription,
|
|
462
|
+
),
|
|
459
463
|
widget: 'email',
|
|
460
464
|
},
|
|
461
465
|
password: {
|
|
@@ -463,8 +467,9 @@ class UsersControlpanel extends Component {
|
|
|
463
467
|
messages.addUserFormPasswordTitle,
|
|
464
468
|
),
|
|
465
469
|
type: 'password',
|
|
466
|
-
description:
|
|
467
|
-
|
|
470
|
+
description: this.props.intl.formatMessage(
|
|
471
|
+
messages.addUserFormPasswordDescription,
|
|
472
|
+
),
|
|
468
473
|
widget: 'password',
|
|
469
474
|
},
|
|
470
475
|
sendPasswordReset: {
|
|
@@ -480,7 +485,6 @@ class UsersControlpanel extends Component {
|
|
|
480
485
|
type: 'array',
|
|
481
486
|
choices: this.props.roles.map((role) => [role.id, role.id]),
|
|
482
487
|
noValueOption: false,
|
|
483
|
-
description: '',
|
|
484
488
|
},
|
|
485
489
|
groups: {
|
|
486
490
|
title: this.props.intl.formatMessage(
|
|
@@ -492,7 +496,6 @@ class UsersControlpanel extends Component {
|
|
|
492
496
|
group.id,
|
|
493
497
|
]),
|
|
494
498
|
noValueOption: false,
|
|
495
|
-
description: '',
|
|
496
499
|
},
|
|
497
500
|
},
|
|
498
501
|
required: ['username', 'email'],
|
|
@@ -43,7 +43,7 @@ const NumberWidget = (props) => {
|
|
|
43
43
|
disabled={isDisabled}
|
|
44
44
|
min={minimum || null}
|
|
45
45
|
max={maximum || null}
|
|
46
|
-
value={value}
|
|
46
|
+
value={value ?? ''}
|
|
47
47
|
placeholder={placeholder}
|
|
48
48
|
onChange={({ target }) =>
|
|
49
49
|
onChange(id, target.value === '' ? undefined : target.value)
|
|
@@ -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,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
class ErrorBoundary extends React.Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = { hasError: false };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static getDerivedStateFromError(error) {
|
|
10
|
+
// Update state so the next render will show the fallback UI.
|
|
11
|
+
return { hasError: true };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
componentDidCatch(error, errorInfo) {
|
|
15
|
+
// eslint-disable-next-line
|
|
16
|
+
console.error(error, errorInfo);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
render() {
|
|
20
|
+
if (this.state.hasError) {
|
|
21
|
+
// You can render any custom fallback UI
|
|
22
|
+
return <pre className="error">{`<error: ${this.props.name}>`}</pre>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return this.props.children;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default ErrorBoundary;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer from 'react-test-renderer';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { Provider } from 'react-intl-redux';
|
|
5
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
6
|
+
import ErrorBoundary from './ErrorBoundary';
|
|
7
|
+
|
|
8
|
+
const mockStore = configureStore();
|
|
9
|
+
|
|
10
|
+
describe('Error boundary', () => {
|
|
11
|
+
it('renders an Error', () => {
|
|
12
|
+
const store = mockStore({
|
|
13
|
+
intl: {
|
|
14
|
+
locale: 'en',
|
|
15
|
+
messages: {},
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
const ThrowError = () => {
|
|
19
|
+
throw new Error('Test');
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const component = renderer.create(
|
|
23
|
+
<Provider store={store}>
|
|
24
|
+
<MemoryRouter>
|
|
25
|
+
<ErrorBoundary name={'test'}>
|
|
26
|
+
<ThrowError />
|
|
27
|
+
</ErrorBoundary>
|
|
28
|
+
</MemoryRouter>
|
|
29
|
+
</Provider>,
|
|
30
|
+
);
|
|
31
|
+
const json = component.toJSON();
|
|
32
|
+
expect(json).toMatchSnapshot();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from '@plone/volto/helpers';
|
|
10
10
|
import StyleWrapper from '@plone/volto/components/manage/Blocks/Block/StyleWrapper';
|
|
11
11
|
import config from '@plone/volto/registry';
|
|
12
|
+
import { ViewDefaultBlock } from '@plone/volto/components';
|
|
12
13
|
|
|
13
14
|
const messages = defineMessages({
|
|
14
15
|
unknownBlock: {
|
|
@@ -32,7 +33,8 @@ const RenderBlocks = (props) => {
|
|
|
32
33
|
<CustomTag>
|
|
33
34
|
{map(content[blocksLayoutFieldname].items, (block) => {
|
|
34
35
|
const Block =
|
|
35
|
-
blocksConfig[content[blocksFieldname]?.[block]?.['@type']]?.view
|
|
36
|
+
blocksConfig[content[blocksFieldname]?.[block]?.['@type']]?.view ||
|
|
37
|
+
ViewDefaultBlock;
|
|
36
38
|
|
|
37
39
|
const blockData = applyBlockDefaults({
|
|
38
40
|
data: content[blocksFieldname][block],
|
|
@@ -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
|
});
|
|
@@ -114,6 +114,24 @@ export const messages = defineMessages({
|
|
|
114
114
|
id: 'Username',
|
|
115
115
|
defaultMessage: 'Username',
|
|
116
116
|
},
|
|
117
|
+
addUserFormUsernameDescription: {
|
|
118
|
+
id: 'addUserFormUsernameDescription',
|
|
119
|
+
defaultMessage:
|
|
120
|
+
'Enter a user name, usually something like "jsmith". No spaces or special characters. Usernames and passwords are case sensitive, make sure the caps lock key is not enabled. This is the name used to log in.',
|
|
121
|
+
},
|
|
122
|
+
addUserFormFullnameDescription: {
|
|
123
|
+
id: 'addUserFormFullnameDescription',
|
|
124
|
+
defaultMessage: 'Enter full name, e.g. John Smith.',
|
|
125
|
+
},
|
|
126
|
+
addUserFormEmailDescription: {
|
|
127
|
+
id: 'addUserFormEmailDescription',
|
|
128
|
+
defaultMessage:
|
|
129
|
+
'Enter an email address. This is necessary in case the password is lost. We respect your privacy, and will not give the address away to any third parties or expose it anywhere.',
|
|
130
|
+
},
|
|
131
|
+
addUserFormPasswordDescription: {
|
|
132
|
+
id: 'addUserFormPasswordDescription',
|
|
133
|
+
defaultMessage: 'Enter your new password. Minimum 8 characters.',
|
|
134
|
+
},
|
|
117
135
|
addGroupsFormTitleTitle: {
|
|
118
136
|
id: 'Title',
|
|
119
137
|
defaultMessage: 'Title',
|
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: {
|
|
@@ -163,3 +165,8 @@ config.set('widgets', {
|
|
|
163
165
|
});
|
|
164
166
|
|
|
165
167
|
config.set('components', {});
|
|
168
|
+
config.set('experimental', {
|
|
169
|
+
addBlockButton: {
|
|
170
|
+
enabled: false,
|
|
171
|
+
},
|
|
172
|
+
});
|