@plone/volto 18.0.0-alpha.42 → 18.0.0-alpha.43

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/finalreleasechangelog.py +48 -0
  3. package/locales/ca/LC_MESSAGES/volto.po +8 -12
  4. package/locales/ca.json +1 -1
  5. package/locales/de/LC_MESSAGES/volto.po +9 -13
  6. package/locales/de.json +1 -1
  7. package/locales/en/LC_MESSAGES/volto.po +8 -12
  8. package/locales/en.json +1 -1
  9. package/locales/es/LC_MESSAGES/volto.po +9 -13
  10. package/locales/es.json +1 -1
  11. package/locales/eu/LC_MESSAGES/volto.po +9 -13
  12. package/locales/eu.json +1 -1
  13. package/locales/fi/LC_MESSAGES/volto.po +9 -13
  14. package/locales/fi.json +1 -1
  15. package/locales/fr/LC_MESSAGES/volto.po +9 -13
  16. package/locales/fr.json +1 -1
  17. package/locales/hi/LC_MESSAGES/volto.po +9 -13
  18. package/locales/hi.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +9 -13
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +8 -12
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +8 -12
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +8 -12
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +9 -13
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +8 -12
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +9 -13
  32. package/locales/zh_CN/LC_MESSAGES/volto.po +9 -13
  33. package/locales/zh_CN.json +1 -1
  34. package/package.json +3 -3
  35. package/razzle.config.js +1 -1
  36. package/src/components/manage/Actions/Actions.stories.jsx +138 -0
  37. package/src/components/manage/Add/Add.jsx +7 -4
  38. package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
  39. package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
  40. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
  41. package/src/components/manage/Blocks/Block/Order/Item.jsx +3 -1
  42. package/src/components/manage/Blocks/Grid/View.jsx +3 -0
  43. package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
  44. package/src/components/manage/Blocks/Search/components/SortOn.jsx +82 -55
  45. package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
  46. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
  47. package/src/components/manage/Blocks/ToC/Edit.jsx +36 -29
  48. package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
  49. package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
  50. package/src/components/manage/Contents/Contents.jsx +3 -0
  51. package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
  52. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
  53. package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
  54. package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
  55. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
  56. package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
  57. package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
  58. package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
  59. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
  60. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
  61. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
  62. package/src/components/manage/Display/Display.jsx +92 -148
  63. package/src/components/manage/Display/Display.stories.jsx +46 -0
  64. package/src/components/manage/Edit/Edit.jsx +2 -4
  65. package/src/components/manage/Preferences/ChangePassword.jsx +94 -172
  66. package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
  67. package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
  68. package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
  69. package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
  70. package/src/components/manage/Toolbar/More.jsx +308 -399
  71. package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
  72. package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
  73. package/src/components/theme/Register/Register.jsx +70 -142
  74. package/src/components/theme/Register/Register.stories.jsx +49 -0
  75. package/src/components/theme/Tags/Tags.jsx +19 -10
  76. package/src/components/theme/Tags/Tags.test.jsx +9 -11
  77. package/src/components/theme/View/AlbumView.jsx +122 -167
  78. package/src/components/theme/View/LinkView.jsx +4 -0
  79. package/src/components/theme/View/LinkView.test.jsx +2 -0
  80. package/src/components/theme/View/View.jsx +0 -6
  81. package/src/config/ControlPanels.js +49 -43
  82. package/src/config/config.test.js +1 -0
  83. package/src/config/index.js +16 -0
  84. package/src/config/slots.js +12 -0
  85. package/src/helpers/Blocks/Blocks.js +12 -7
  86. package/src/helpers/Blocks/Blocks.test.js +15 -0
  87. package/src/helpers/Blocks/cloneBlocks.ts +1 -1
  88. package/src/helpers/FormValidation/FormValidation.jsx +19 -2
  89. package/src/helpers/FormValidation/validators.ts +1 -1
  90. package/src/helpers/Url/Url.test.js +15 -2
  91. package/src/helpers/Url/urlRegex.js +1 -1
  92. package/src/helpers/index.js +2 -0
  93. package/src/middleware/api.js +4 -2
  94. package/src/middleware/index.js +1 -0
  95. package/src/middleware/userSessionReset.js +46 -0
  96. package/src/store.js +2 -0
  97. package/test-setup-config.jsx +3 -0
  98. package/theme/themes/pastanaga/extras/blocks.less +6 -0
  99. package/types/components/manage/Actions/Actions.stories.d.ts +8 -0
  100. package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
  101. package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
  102. package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
  103. package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
  104. package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
  105. package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
  106. package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
  107. package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
  108. package/types/components/manage/Contents/index.d.ts +1 -1
  109. package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
  110. package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
  111. package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
  112. package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
  113. package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
  114. package/types/components/manage/Controlpanels/index.d.ts +4 -4
  115. package/types/components/manage/Display/Display.stories.d.ts +8 -0
  116. package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
  117. package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
  118. package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
  119. package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
  120. package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
  121. package/types/components/manage/Toolbar/More.d.ts +8 -5
  122. package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
  123. package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
  124. package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
  125. package/types/components/manage/Widgets/index.d.ts +1 -1
  126. package/types/components/theme/Register/Register.d.ts +2 -2
  127. package/types/components/theme/Register/Register.stories.d.ts +9 -0
  128. package/types/components/theme/Tags/Tags.d.ts +15 -7
  129. package/types/components/theme/View/AlbumView.d.ts +3 -17
  130. package/types/config/ControlPanels.d.ts +8 -0
  131. package/types/config/Widgets.d.ts +1 -1
  132. package/types/config/slots.d.ts +21 -0
  133. package/types/helpers/Blocks/Blocks.d.ts +6 -0
  134. package/types/helpers/FormValidation/FormValidation.d.ts +1 -0
  135. package/types/helpers/index.d.ts +2 -2
  136. package/types/middleware/index.d.ts +1 -0
  137. package/types/middleware/userSessionReset.d.ts +5 -0
@@ -1,134 +1,86 @@
1
- /**
2
- * Users controlpanel groups.
3
- * @module components/manage/Controlpanels/UsersControlpanelGroups
4
- */
5
1
  import PropTypes from 'prop-types';
6
- import React, { Component } from 'react';
7
- import { FormattedMessage, injectIntl } from 'react-intl';
2
+ import { FormattedMessage } from 'react-intl';
8
3
  import { Dropdown, Table, Checkbox } from 'semantic-ui-react';
9
4
  import trashSVG from '@plone/volto/icons/delete.svg';
10
5
  import ploneSVG from '@plone/volto/icons/plone.svg';
11
6
  import { Icon } from '@plone/volto/components';
12
7
  import { canAssignRole } from '@plone/volto/helpers';
13
8
 
14
- /**
15
- * UsersControlpanelGroups class.
16
- * @class UsersControlpanelGroups
17
- * @extends Component
18
- */
19
- class RenderGroups extends Component {
20
- /**
21
- * Property types.
22
- * @property {Object} propTypes Property types.
23
- * @static
24
- */
25
- static propTypes = {
26
- //single group
27
- group: PropTypes.shape({
28
- title: PropTypes.string,
29
- description: PropTypes.string,
30
- email: PropTypes.string,
31
- groupname: PropTypes.string,
32
- roles: PropTypes.arrayOf(PropTypes.string),
33
- }).isRequired,
34
-
35
- roles: PropTypes.arrayOf(
36
- PropTypes.shape({
37
- id: PropTypes.string,
38
- }),
39
- ).isRequired,
40
- inheritedRole: PropTypes.array,
41
- onDelete: PropTypes.func.isRequired,
42
- isUserManager: PropTypes.bool.isRequired,
9
+ const RenderGroups = (props) => {
10
+ const onChange = (event, { value }) => {
11
+ const [group, role] = value.split('.');
12
+ props.updateGroups(group, role);
43
13
  };
44
-
45
- /**
46
- * Constructor
47
- * @method constructor
48
- * @param {Object} props Component properties
49
- * @constructs Sharing
50
- */
51
- constructor(props) {
52
- super(props);
53
- this.onChange = this.onChange.bind(this);
54
- }
55
-
56
- /**
57
- * @param {*} event
58
- * @param {*} { value }
59
- * @memberof UsersControlpanelUser
60
- */
61
- onChange(event, { value }) {
62
- const [group, role] = value.split('&role=');
63
- this.props.updateGroups(group, role);
64
- }
65
-
66
- /**
67
- *@param {*}
68
- *@returns {Boolean}
69
- *@memberof RenderGroups
70
- */
71
- isAuthGroup = (roleId) => {
72
- return this.props.inheritedRole.includes(roleId);
14
+ const isAuthGroup = (roleId) => {
15
+ return props.inheritedRole.includes(roleId);
73
16
  };
74
-
75
- canDeleteGroup() {
76
- if (this.props.isUserManager) return true;
77
- return !this.props.group.roles.includes('Manager');
78
- }
79
-
80
- /**
81
- * Render method.
82
- * @method render
83
- * @returns {string} Markup for the component.
84
- */
85
- render() {
86
- return (
87
- <Table.Row key={this.props.group.title}>
88
- <Table.Cell>{this.props.group.groupname}</Table.Cell>
89
- {this.props.roles.map((role) => (
90
- <Table.Cell key={role.id}>
91
- {this.props.inheritedRole &&
92
- this.props.inheritedRole.includes(role.id) &&
93
- this.props.group.roles.includes('Authenticated') ? (
94
- <Icon
95
- name={ploneSVG}
96
- size="20px"
97
- color="#007EB1"
98
- title={'plone-svg'}
99
- />
100
- ) : (
101
- <Checkbox
102
- checked={
103
- this.props.group.id === 'AuthenticatedUsers'
104
- ? this.isAuthGroup(role.id)
105
- : this.props.group.roles.includes(role.id)
106
- }
107
- onChange={this.onChange}
108
- value={`${this.props.group.id}&role=${role.id}`}
109
- disabled={!canAssignRole(this.props.isUserManager, role)}
110
- />
111
- )}
112
- </Table.Cell>
113
- ))}
114
- <Table.Cell textAlign="right">
115
- {this.canDeleteGroup() && (
116
- <Dropdown icon="ellipsis horizontal">
117
- <Dropdown.Menu className="left">
118
- <Dropdown.Item
119
- onClick={this.props.onDelete}
120
- value={this.props.group['@id']}
121
- >
122
- <Icon name={trashSVG} size="15px" />
123
- <FormattedMessage id="Delete" defaultMessage="Delete" />
124
- </Dropdown.Item>
125
- </Dropdown.Menu>
126
- </Dropdown>
17
+ const canDeleteGroup = () => {
18
+ if (props.isUserManager) return true;
19
+ return !props.group.roles.includes('Manager');
20
+ };
21
+ return (
22
+ <Table.Row key={props.group.title}>
23
+ <Table.Cell>{props.group.groupname}</Table.Cell>
24
+ {props.roles.map((role) => (
25
+ <Table.Cell key={role.id}>
26
+ {props.inheritedRole &&
27
+ props.inheritedRole.includes(role.id) &&
28
+ props.group.roles.includes('Authenticated') ? (
29
+ <Icon
30
+ name={ploneSVG}
31
+ size="20px"
32
+ color="#007EB1"
33
+ title={'plone-svg'}
34
+ />
35
+ ) : (
36
+ <Checkbox
37
+ checked={
38
+ props.group.id === 'AuthenticatedUsers'
39
+ ? isAuthGroup(role.id)
40
+ : props.group.roles.includes(role.id)
41
+ }
42
+ onChange={onChange}
43
+ value={`${props.group.id}.${role.id}`}
44
+ disabled={!canAssignRole(props.isUserManager, role)}
45
+ />
127
46
  )}
128
47
  </Table.Cell>
129
- </Table.Row>
130
- );
131
- }
132
- }
48
+ ))}
49
+ <Table.Cell textAlign="right">
50
+ {canDeleteGroup() && (
51
+ <Dropdown icon="ellipsis horizontal">
52
+ <Dropdown.Menu className="left">
53
+ <Dropdown.Item
54
+ onClick={props.onDelete}
55
+ value={props.group['@id']}
56
+ >
57
+ <Icon name={trashSVG} size="15px" />
58
+ <FormattedMessage id="Delete" defaultMessage="Delete" />
59
+ </Dropdown.Item>
60
+ </Dropdown.Menu>
61
+ </Dropdown>
62
+ )}
63
+ </Table.Cell>
64
+ </Table.Row>
65
+ );
66
+ };
67
+
68
+ RenderGroups.propTypes = {
69
+ //single group
70
+ group: PropTypes.shape({
71
+ title: PropTypes.string,
72
+ description: PropTypes.string,
73
+ email: PropTypes.string,
74
+ groupname: PropTypes.string,
75
+ roles: PropTypes.arrayOf(PropTypes.string),
76
+ }).isRequired,
133
77
 
134
- export default injectIntl(RenderGroups);
78
+ roles: PropTypes.arrayOf(
79
+ PropTypes.shape({
80
+ id: PropTypes.string,
81
+ }),
82
+ ).isRequired,
83
+ inheritedRole: PropTypes.array,
84
+ onDelete: PropTypes.func.isRequired,
85
+ };
86
+ export default RenderGroups;
@@ -1,14 +1,14 @@
1
- import React, { Component, Fragment } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { connect } from 'react-redux';
3
+ import { useDispatch, useSelector } from 'react-redux';
4
4
  import { compose } from 'redux';
5
5
  import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
6
6
 
7
7
  import { getSchema, updateContent, getContent } from '@plone/volto/actions';
8
8
  import { getLayoutFieldname } from '@plone/volto/helpers';
9
- import { Icon } from '@plone/volto/components';
10
- import { FormFieldWrapper } from '@plone/volto/components/manage/Widgets';
11
- import { defineMessages, injectIntl } from 'react-intl';
9
+ import { usePrevious } from '@plone/volto/helpers';
10
+ import { FormFieldWrapper, Icon } from '@plone/volto/components';
11
+ import { defineMessages, useIntl } from 'react-intl';
12
12
  import config from '@plone/volto/registry';
13
13
 
14
14
  import downSVG from '@plone/volto/icons/down-key.svg';
@@ -110,152 +110,96 @@ const customSelectStyles = {
110
110
  }),
111
111
  };
112
112
 
113
- /**
114
- * Display container class.
115
- * @class Display
116
- * @extends Component
117
- */
118
- class DisplaySelect extends Component {
119
- /**
120
- * Property types.
121
- * @property {Object} propTypes Property types.
122
- * @static
123
- */
124
- static propTypes = {
125
- getSchema: PropTypes.func.isRequired,
126
- updateContent: PropTypes.func.isRequired,
127
- getContent: PropTypes.func.isRequired,
128
- loaded: PropTypes.bool.isRequired,
129
- pathname: PropTypes.string.isRequired,
130
- layouts: PropTypes.arrayOf(PropTypes.string),
131
- layout: PropTypes.string,
132
- type: PropTypes.string.isRequired,
133
- };
134
-
135
- /**
136
- * Default properties
137
- * @property {Object} defaultProps Default properties.
138
- * @static
139
- */
140
- static defaultProps = {
141
- layouts: [],
142
- layout: '',
143
- };
144
-
145
- state = {
146
- selectedOption: {
147
- value: this.props.layout,
148
- label:
149
- this.props.intl.formatMessage({
150
- id: config.views.layoutViewsNamesMapping?.[this.props.layout],
151
- defaultMessage:
152
- config.views.layoutViewsNamesMapping?.[this.props.layout],
153
- }) || this.props.layout,
154
- },
155
- };
156
-
157
- componentDidMount() {
158
- this.props.getSchema(this.props.type);
159
- }
160
-
161
- /**
162
- * Component will receive props
163
- * @method componentWillReceiveProps
164
- * @param {Object} nextProps Next properties
165
- * @returns {undefined}
166
- */
167
- UNSAFE_componentWillReceiveProps(nextProps) {
168
- if (nextProps.pathname !== this.props.pathname) {
169
- this.props.getSchema(nextProps.type);
113
+ const DisplaySelect = (props) => {
114
+ const { pathname } = props;
115
+ const intl = useIntl();
116
+ const dispatch = useDispatch();
117
+ const loaded = useSelector((state) => state.content.update.loaded);
118
+ const layouts = useSelector((state) =>
119
+ state.schema.schema ? state.schema.schema.layouts : [],
120
+ );
121
+ const layout = useSelector((state) =>
122
+ state.content.data
123
+ ? state.content.data[getLayoutFieldname(state.content.data)]
124
+ : '',
125
+ );
126
+ const [selectedOption, setselectedOption] = useState({
127
+ value: layout,
128
+ label:
129
+ intl.formatMessage({
130
+ id: config.views.layoutViewsNamesMapping?.[layout],
131
+ defaultMessage: config.views.layoutViewsNamesMapping?.[layout],
132
+ }) || layout,
133
+ });
134
+
135
+ const type = useSelector((state) =>
136
+ state.content.data ? state.content.data['@type'] : '',
137
+ );
138
+ const prevloaded = usePrevious(loaded);
139
+ const prevpathname = usePrevious(pathname);
140
+
141
+ useEffect(() => {
142
+ dispatch(getSchema(type));
143
+ }, [dispatch, type]);
144
+ useEffect(() => {
145
+ if (pathname !== prevpathname) {
146
+ dispatch(getSchema(type));
170
147
  }
171
- if (!this.props.loaded && nextProps.loaded) {
172
- this.props.getContent(nextProps.pathname);
148
+ if (!prevloaded && loaded) {
149
+ dispatch(getContent(pathname));
173
150
  }
174
- }
175
-
176
- /**
177
- * On set layout handler
178
- * @method setLayout
179
- * @param {Object} event Event object
180
- * @returns {undefined}
181
- */
182
- setLayout = (selectedOption) => {
183
- this.props.updateContent(this.props.pathname, {
184
- layout: selectedOption.value,
185
- });
186
- this.setState({ selectedOption });
151
+ }, [dispatch, type, pathname, prevpathname, prevloaded, loaded]);
152
+
153
+ const setLayout = (selectedOption) => {
154
+ dispatch(
155
+ updateContent(pathname, {
156
+ layout: selectedOption.value,
157
+ }),
158
+ );
159
+ setselectedOption(selectedOption);
187
160
  };
188
161
 
189
- selectValue = (option) => (
190
- <Fragment>
191
- <span className="Select-value-label">{option.label}</span>
192
- </Fragment>
193
- );
194
-
195
- optionRenderer = (option) => (
196
- <Fragment>
197
- <span style={{ marginRight: 'auto' }}>{option.label}</span>
198
- <Icon name={checkSVG} size="24px" />
199
- </Fragment>
200
- );
201
-
202
- render() {
203
- const { selectedOption } = this.state;
204
- const Select = this.props.reactSelect.default;
205
- const layoutsNames = config.views.layoutViewsNamesMapping;
206
- const layoutOptions = this.props.layouts
207
- .filter(
208
- (layout) =>
209
- Object.keys(config.views.contentTypesViews).includes(layout) ||
210
- Object.keys(config.views.layoutViews).includes(layout),
211
- )
212
- .map((item) => ({
213
- value: item,
214
- label:
215
- this.props.intl.formatMessage({
216
- id: layoutsNames[item],
217
- defaultMessage: layoutsNames[item],
218
- }) || item,
219
- }));
162
+ const Select = props.reactSelect.default;
163
+ const layoutsNames = config.views.layoutViewsNamesMapping;
164
+ const layoutOptions = layouts
165
+ .filter(
166
+ (layout) =>
167
+ Object.keys(config.views.contentTypesViews).includes(layout) ||
168
+ Object.keys(config.views.layoutViews).includes(layout),
169
+ )
170
+ .map((item) => ({
171
+ value: item,
172
+ label:
173
+ intl.formatMessage({
174
+ id: layoutsNames[item],
175
+ defaultMessage: layoutsNames[item],
176
+ }) || item,
177
+ }));
178
+
179
+ return layoutOptions?.length > 1 ? (
180
+ <FormFieldWrapper
181
+ id="display-select"
182
+ title={intl.formatMessage(messages.Viewmode)}
183
+ {...props}
184
+ >
185
+ <Select
186
+ name="display-select"
187
+ className="react-select-container"
188
+ classNamePrefix="react-select"
189
+ options={layoutOptions}
190
+ styles={customSelectStyles}
191
+ theme={selectTheme}
192
+ components={{ DropdownIndicator, Option }}
193
+ onChange={setLayout}
194
+ defaultValue={selectedOption}
195
+ isSearchable={false}
196
+ />
197
+ </FormFieldWrapper>
198
+ ) : null;
199
+ };
220
200
 
221
- return layoutOptions?.length > 1 ? (
222
- <FormFieldWrapper
223
- id="display-select"
224
- title={this.props.intl.formatMessage(messages.Viewmode)}
225
- {...this.props}
226
- >
227
- <Select
228
- name="display-select"
229
- className="react-select-container"
230
- classNamePrefix="react-select"
231
- options={layoutOptions}
232
- styles={customSelectStyles}
233
- theme={selectTheme}
234
- components={{ DropdownIndicator, Option }}
235
- onChange={this.setLayout}
236
- defaultValue={selectedOption}
237
- isSearchable={false}
238
- />
239
- </FormFieldWrapper>
240
- ) : null;
241
- }
242
- }
201
+ DisplaySelect.propTypes = {
202
+ pathname: PropTypes.string.isRequired,
203
+ };
243
204
 
244
- export default compose(
245
- injectIntl,
246
- injectLazyLibs('reactSelect'),
247
- connect(
248
- (state) => ({
249
- loaded: state.content.update.loaded,
250
- layouts: state.schema.schema ? state.schema.schema.layouts : [],
251
- layout: state.content.data
252
- ? state.content.data[getLayoutFieldname(state.content.data)]
253
- : '',
254
- layout_fieldname: state.content.data
255
- ? getLayoutFieldname(state.content.data)
256
- : '',
257
- type: state.content.data ? state.content.data['@type'] : '',
258
- }),
259
- { getSchema, updateContent, getContent },
260
- ),
261
- )(DisplaySelect);
205
+ export default compose(injectLazyLibs('reactSelect'))(DisplaySelect);
@@ -0,0 +1,46 @@
1
+ import { injectIntl } from 'react-intl';
2
+ import React from 'react';
3
+ import DisplayComponent from './Display';
4
+ import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
5
+
6
+ const IntlDisplayComponent = injectIntl(DisplayComponent);
7
+
8
+ function StoryComponent(args) {
9
+ return (
10
+ <Wrapper
11
+ customStore={{
12
+ content: {
13
+ update: { loaded: true },
14
+ data: { layout: 'summary_view', '@type': 'Folder' },
15
+ },
16
+ schema: {
17
+ schema: {
18
+ layouts: ['summary_view', 'listing_view'],
19
+ },
20
+ },
21
+ intl: {
22
+ locale: 'en',
23
+ messages: {},
24
+ },
25
+ }}
26
+ >
27
+ <div id="toolbar" style={{ display: 'none' }} />
28
+ <IntlDisplayComponent {...args} pathname="/test" />
29
+ </Wrapper>
30
+ );
31
+ }
32
+
33
+ export const Display = StoryComponent.bind({});
34
+
35
+ export default {
36
+ title: 'Public components/Display',
37
+ component: Display,
38
+ decorators: [
39
+ (Story) => (
40
+ <div className="ui segment form attached" style={{ width: '400px' }}>
41
+ <Story />
42
+ </div>
43
+ ),
44
+ ],
45
+ argTypes: {},
46
+ };
@@ -5,7 +5,7 @@
5
5
 
6
6
  import React, { Component } from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { Helmet } from '@plone/volto/helpers';
8
+ import { Helmet, extractInvariantErrors } from '@plone/volto/helpers';
9
9
  import { connect } from 'react-redux';
10
10
  import { compose } from 'redux';
11
11
  import { asyncConnect, hasApiExpander } from '@plone/volto/helpers';
@@ -208,9 +208,7 @@ class Edit extends Component {
208
208
  const errorsList = tryParseJSON(error);
209
209
  let erroMessage;
210
210
  if (Array.isArray(errorsList)) {
211
- const invariantErrors = errorsList
212
- .filter((errorItem) => !('field' in errorItem))
213
- .map((errorItem) => errorItem['message']);
211
+ const invariantErrors = extractInvariantErrors(errorsList);
214
212
  if (invariantErrors.length > 0) {
215
213
  // Plone invariant validation message.
216
214
  erroMessage = invariantErrors.join(' - ');