@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,25 +1,16 @@
1
- /**
2
- * Change password component.
3
- * @module components/manage/Preferences/ChangePassword
4
- */
5
-
6
- import React, { Component } from 'react';
7
- import PropTypes from 'prop-types';
8
- import { Helmet } from '@plone/volto/helpers';
9
- import { connect } from 'react-redux';
10
- import { compose } from 'redux';
11
- import { Link, withRouter } from 'react-router-dom';
1
+ import { useSelector, useDispatch, shallowEqual } from 'react-redux';
2
+ import { Link, useHistory, useLocation } from 'react-router-dom';
3
+ import { defineMessages, useIntl } from 'react-intl';
12
4
  import { createPortal } from 'react-dom';
13
- import { defineMessages, injectIntl } from 'react-intl';
14
5
  import { Container } from 'semantic-ui-react';
15
6
  import jwtDecode from 'jwt-decode';
16
7
  import { toast } from 'react-toastify';
17
8
 
18
- import { Icon, Toast, Toolbar } from '@plone/volto/components';
19
- import { Form } from '@plone/volto/components/manage/Form';
9
+ import { Helmet } from '@plone/volto/helpers';
10
+ import { useClient } from '@plone/volto/hooks';
11
+ import { Form, Icon, Toast, Toolbar } from '@plone/volto/components';
20
12
  import { updatePassword } from '@plone/volto/actions';
21
13
  import { getBaseUrl } from '@plone/volto/helpers';
22
-
23
14
  import backSVG from '@plone/volto/icons/back.svg';
24
15
 
25
16
  const messages = defineMessages({
@@ -70,169 +61,100 @@ const messages = defineMessages({
70
61
  },
71
62
  });
72
63
 
73
- /**
74
- * ChangePassword class.
75
- * @class ChangePassword
76
- * @extends Component
77
- */
78
- class ChangePassword extends Component {
79
- /**
80
- * Property types.
81
- * @property {Object} propTypes Property types.
82
- * @static
83
- */
84
- static propTypes = {
85
- userId: PropTypes.string.isRequired,
86
- loading: PropTypes.bool.isRequired,
87
- updatePassword: PropTypes.func.isRequired,
88
- pathname: PropTypes.string.isRequired,
89
- };
90
-
91
- /**
92
- * Constructor
93
- * @method constructor
94
- * @param {Object} props Component properties
95
- * @constructs ChangePassword
96
- */
97
- constructor(props) {
98
- super(props);
99
- this.onCancel = this.onCancel.bind(this);
100
- this.onSubmit = this.onSubmit.bind(this);
101
- this.state = { isClient: false };
102
- }
64
+ const ChangePassword = () => {
65
+ const intl = useIntl();
66
+ const dispatch = useDispatch();
67
+ const isClient = useClient();
103
68
 
104
- /**
105
- * Component did mount
106
- * @method componentDidMount
107
- * @returns {undefined}
108
- */
109
- componentDidMount() {
110
- this.setState({ isClient: true });
111
- }
69
+ const userId = useSelector(
70
+ (state) =>
71
+ state.userSession.token ? jwtDecode(state.userSession.token).sub : '',
72
+ shallowEqual,
73
+ );
74
+ const loading = useSelector((state) => state.users.update_password.loading);
75
+ const { pathname } = useLocation();
76
+ const history = useHistory();
112
77
 
113
- /**
114
- * Submit handler
115
- * @method onSubmit
116
- * @param {object} data Form data.
117
- * @returns {undefined}
118
- */
119
- onSubmit(data) {
78
+ const onSubmit = (data) => {
120
79
  if (data.newPassword === data.newPasswordRepeat) {
121
- this.props.updatePassword(
122
- this.props.userId,
123
- data.oldPassword,
124
- data.newPassword,
125
- );
126
- toast.success(
127
- <Toast
128
- success
129
- title={this.props.intl.formatMessage(messages.success)}
130
- content={this.props.intl.formatMessage(messages.saved)}
131
- />,
80
+ dispatch(updatePassword(userId, data.oldPassword, data.newPassword)).then(
81
+ () => {
82
+ toast.success(
83
+ <Toast
84
+ success
85
+ title={intl.formatMessage(messages.success)}
86
+ content={intl.formatMessage(messages.saved)}
87
+ />,
88
+ );
89
+ },
132
90
  );
133
91
  }
134
- }
92
+ };
135
93
 
136
- /**
137
- * Cancel handler
138
- * @method onCancel
139
- * @returns {undefined}
140
- */
141
- onCancel() {
142
- this.props.history.goBack();
143
- }
94
+ const onCancel = () => {
95
+ history.goBack();
96
+ };
144
97
 
145
- /**
146
- * Render method.
147
- * @method render
148
- * @returns {string} Markup for the component.
149
- */
150
- render() {
151
- return (
152
- <Container id="page-change-password">
153
- <Helmet
154
- title={this.props.intl.formatMessage(messages.changePassword)}
155
- />
156
- <Form
157
- schema={{
158
- fieldsets: [
159
- {
160
- id: 'default',
161
- title: this.props.intl.formatMessage(messages.default),
162
- fields: ['oldPassword', 'newPassword', 'newPasswordRepeat'],
163
- },
164
- ],
165
- properties: {
166
- oldPassword: {
167
- description: this.props.intl.formatMessage(
168
- messages.oldPasswordDescription,
169
- ),
170
- title: this.props.intl.formatMessage(messages.oldPasswordTitle),
171
- type: 'string',
172
- widget: 'password',
173
- },
174
- newPassword: {
175
- description: this.props.intl.formatMessage(
176
- messages.newPasswordDescription,
177
- ),
178
- title: this.props.intl.formatMessage(messages.newPasswordTitle),
179
- type: 'string',
180
- widget: 'password',
181
- },
182
- newPasswordRepeat: {
183
- description: this.props.intl.formatMessage(
184
- messages.newPasswordRepeatDescription,
185
- ),
186
- title: this.props.intl.formatMessage(
187
- messages.newPasswordRepeatTitle,
188
- ),
189
- type: 'string',
190
- widget: 'password',
191
- },
98
+ return (
99
+ <Container id="page-change-password">
100
+ <Helmet title={intl.formatMessage(messages.changePassword)} />
101
+ <Form
102
+ schema={{
103
+ fieldsets: [
104
+ {
105
+ id: 'default',
106
+ title: intl.formatMessage(messages.default),
107
+ fields: ['oldPassword', 'newPassword', 'newPasswordRepeat'],
192
108
  },
193
- required: ['oldPassword', 'newPassword', 'newPasswordRepeat'],
194
- }}
195
- onSubmit={this.onSubmit}
196
- onCancel={this.onCancel}
197
- loading={this.props.loading}
198
- />
199
- {this.state.isClient &&
200
- createPortal(
201
- <Toolbar
202
- pathname={this.props.pathname}
203
- hideDefaultViewButtons
204
- inner={
205
- <Link
206
- to={`${getBaseUrl(this.props.pathname)}`}
207
- className="item"
208
- >
209
- <Icon
210
- name={backSVG}
211
- className="contents circled"
212
- size="30px"
213
- title={this.props.intl.formatMessage(messages.back)}
214
- />
215
- </Link>
216
- }
217
- />,
218
- document.getElementById('toolbar'),
219
- )}
220
- </Container>
221
- );
222
- }
223
- }
109
+ ],
110
+ properties: {
111
+ oldPassword: {
112
+ description: intl.formatMessage(messages.oldPasswordDescription),
113
+ title: intl.formatMessage(messages.oldPasswordTitle),
114
+ type: 'string',
115
+ widget: 'password',
116
+ },
117
+ newPassword: {
118
+ description: intl.formatMessage(messages.newPasswordDescription),
119
+ title: intl.formatMessage(messages.newPasswordTitle),
120
+ type: 'string',
121
+ widget: 'password',
122
+ },
123
+ newPasswordRepeat: {
124
+ description: intl.formatMessage(
125
+ messages.newPasswordRepeatDescription,
126
+ ),
127
+ title: intl.formatMessage(messages.newPasswordRepeatTitle),
128
+ type: 'string',
129
+ widget: 'password',
130
+ },
131
+ },
132
+ required: ['oldPassword', 'newPassword', 'newPasswordRepeat'],
133
+ }}
134
+ onSubmit={onSubmit}
135
+ onCancel={onCancel}
136
+ loading={loading}
137
+ />
138
+ {isClient &&
139
+ createPortal(
140
+ <Toolbar
141
+ pathname={pathname}
142
+ hideDefaultViewButtons
143
+ inner={
144
+ <Link to={`${getBaseUrl(pathname)}`} className="item">
145
+ <Icon
146
+ name={backSVG}
147
+ className="contents circled"
148
+ size="30px"
149
+ title={intl.formatMessage(messages.back)}
150
+ />
151
+ </Link>
152
+ }
153
+ />,
154
+ document.getElementById('toolbar'),
155
+ )}
156
+ </Container>
157
+ );
158
+ };
224
159
 
225
- export default compose(
226
- withRouter,
227
- injectIntl,
228
- connect(
229
- (state, props) => ({
230
- userId: state.userSession.token
231
- ? jwtDecode(state.userSession.token).sub
232
- : '',
233
- loading: state.users.update_password.loading,
234
- pathname: props.location.pathname,
235
- }),
236
- { updatePassword },
237
- ),
238
- )(ChangePassword);
160
+ export default ChangePassword;
@@ -0,0 +1,41 @@
1
+ import { injectIntl } from 'react-intl';
2
+ import React from 'react';
3
+ import ChangePasswordComponent from './ChangePassword';
4
+ import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
5
+ const IntlChangePasswordComponent = injectIntl(ChangePasswordComponent);
6
+
7
+ function StoryComponent(args) {
8
+ return (
9
+ <Wrapper
10
+ customStore={{
11
+ intl: {
12
+ locale: 'en',
13
+ messages: {},
14
+ },
15
+ users: {
16
+ update_password: {
17
+ loading: false,
18
+ },
19
+ },
20
+ }}
21
+ >
22
+ <div id="toolbar" style={{ display: 'none' }} />
23
+ <IntlChangePasswordComponent {...args} location={{ pathname: '/blog' }} />
24
+ </Wrapper>
25
+ );
26
+ }
27
+
28
+ export const ChangePassword = StoryComponent.bind({});
29
+
30
+ export default {
31
+ title: 'Public components/ChangePassword',
32
+ component: ChangePassword,
33
+ decorators: [
34
+ (Story) => (
35
+ <div className="ui segment form attached" style={{ width: '400px' }}>
36
+ <Story />
37
+ </div>
38
+ ),
39
+ ],
40
+ argTypes: {},
41
+ };
@@ -1,14 +1,8 @@
1
- /**
2
- * Personal information component.
3
- * @module components/manage/Preferences/PersonalInformation
4
- */
5
-
6
- import React, { Component } from 'react';
1
+ import React, { useEffect } from 'react';
7
2
  import PropTypes from 'prop-types';
8
- import { connect } from 'react-redux';
9
- import { compose } from 'redux';
10
- import { injectIntl } from 'react-intl';
11
- import { withRouter } from 'react-router-dom';
3
+ import { useDispatch, useSelector } from 'react-redux';
4
+ import { useIntl } from 'react-intl';
5
+ import { useHistory } from 'react-router-dom';
12
6
  import jwtDecode from 'jwt-decode';
13
7
  import { toast } from 'react-toastify';
14
8
  import { messages } from '@plone/volto/helpers';
@@ -16,117 +10,58 @@ import { Toast } from '@plone/volto/components';
16
10
  import { Form } from '@plone/volto/components/manage/Form';
17
11
  import { getUser, updateUser, getUserSchema } from '@plone/volto/actions';
18
12
 
19
- /**
20
- * PersonalInformation class.
21
- * @class PersonalInformation
22
- * @extends Component
23
- */
24
- class PersonalInformation extends Component {
25
- /**
26
- * Property types.
27
- * @property {Object} propTypes Property types.
28
- * @static
29
- */
30
- static propTypes = {
31
- user: PropTypes.shape({
32
- fullname: PropTypes.string,
33
- email: PropTypes.string,
34
- home_page: PropTypes.string,
35
- location: PropTypes.string,
36
- }).isRequired,
37
- updateUser: PropTypes.func.isRequired,
38
- getUser: PropTypes.func.isRequired,
39
- userId: PropTypes.string.isRequired,
40
- loaded: PropTypes.bool.isRequired,
41
- loading: PropTypes.bool,
42
- closeMenu: PropTypes.func,
43
- getUserSchema: PropTypes.func.isRequired,
44
- };
45
-
46
- /**
47
- * Constructor
48
- * @method constructor
49
- * @param {Object} props Component properties
50
- * @constructs ChangePassword
51
- */
52
- constructor(props) {
53
- super(props);
54
- this.onCancel = this.onCancel.bind(this);
55
- this.onSubmit = this.onSubmit.bind(this);
56
- }
13
+ const PersonalInformation = (props) => {
14
+ const intl = useIntl();
15
+ const dispatch = useDispatch();
16
+ const history = useHistory();
17
+ const user = useSelector((state) => state.users.user);
18
+ const userId = useSelector((state) =>
19
+ state.userSession.token ? jwtDecode(state.userSession.token).sub : '',
20
+ );
21
+ const loading = useSelector((state) => state.users.update.loading);
22
+ const userschema = useSelector((state) => state.userschema);
57
23
 
58
- componentDidMount() {
59
- this.props.getUser(this.props.userId);
60
- this.props.getUserSchema();
61
- }
24
+ useEffect(() => {
25
+ dispatch(getUser(userId));
26
+ dispatch(getUserSchema());
27
+ }, [dispatch, userId]);
62
28
 
63
- /**
64
- * Submit handler
65
- * @method onSubmit
66
- * @param {object} data Form data.
67
- * @returns {undefined}
68
- */
69
- onSubmit(data) {
70
- // We don't want the user to change his login name/username or the roles
71
- // from this form
72
- // Backend will complain anyways, but we clean the data here before it does
29
+ const onSubmit = (data) => {
73
30
  delete data.id;
74
31
  delete data.username;
75
32
  delete data.roles;
76
- this.props.updateUser(this.props.userId, data);
77
- toast.success(
78
- <Toast
79
- success
80
- title={this.props.intl.formatMessage(messages.success)}
81
- content={this.props.intl.formatMessage(messages.saved)}
82
- />,
33
+ dispatch(updateUser(userId, data)).then(() =>
34
+ toast.success(
35
+ <Toast
36
+ success
37
+ title={intl.formatMessage(messages.success)}
38
+ content={intl.formatMessage(messages.saved)}
39
+ />,
40
+ ),
83
41
  );
84
- if (this.props.closeMenu) this.props.closeMenu();
85
- }
42
+ if (props.closeMenu) props.closeMenu();
43
+ };
86
44
 
87
- /**
88
- * Cancel handler
89
- * @method onCancel
90
- * @returns {undefined}
91
- */
92
- onCancel() {
93
- if (this.props.closeMenu) this.props.closeMenu();
94
- else this.props.history.goBack();
95
- }
45
+ const onCancel = () => {
46
+ if (props.closeMenu) props.closeMenu();
47
+ else history.goBack();
48
+ };
96
49
 
97
- /**
98
- * Render method.
99
- * @method render
100
- * @returns {string} Markup for the component.
101
- */
102
- render() {
103
- return (
104
- this.props?.userschema?.loaded && (
105
- <Form
106
- formData={this.props.user}
107
- schema={this.props?.userschema.userschema}
108
- onSubmit={this.onSubmit}
109
- onCancel={this.onCancel}
110
- loading={this.props.loading}
111
- />
112
- )
113
- );
114
- }
115
- }
50
+ return (
51
+ userschema?.loaded && (
52
+ <Form
53
+ formData={user}
54
+ schema={userschema.userschema}
55
+ onSubmit={onSubmit}
56
+ onCancel={onCancel}
57
+ loading={loading}
58
+ />
59
+ )
60
+ );
61
+ };
62
+
63
+ PersonalInformation.propTypes = {
64
+ closeMenu: PropTypes.func,
65
+ };
116
66
 
117
- export default compose(
118
- withRouter,
119
- injectIntl,
120
- connect(
121
- (state, props) => ({
122
- user: state.users.user,
123
- userId: state.userSession.token
124
- ? jwtDecode(state.userSession.token).sub
125
- : '',
126
- loaded: state.users.get.loaded,
127
- loading: state.users.update.loading,
128
- userschema: state.userschema,
129
- }),
130
- { getUser, updateUser, getUserSchema },
131
- ),
132
- )(PersonalInformation);
67
+ export default PersonalInformation;
@@ -1,16 +1,10 @@
1
- /**
2
- * Personal preferences component.
3
- * @module components/manage/Preferences/PersonalPreferences
4
- */
5
-
6
- import React, { Component } from 'react';
7
1
  import PropTypes from 'prop-types';
8
- import { connect } from 'react-redux';
9
- import { compose } from 'redux';
2
+ import { useDispatch } from 'react-redux';
10
3
  import { map, keys } from 'lodash';
11
- import { withCookies } from 'react-cookie';
12
- import { defineMessages, injectIntl } from 'react-intl';
4
+ import { defineMessages, useIntl } from 'react-intl';
13
5
  import { toast } from 'react-toastify';
6
+ import { compose } from 'redux';
7
+ import { withCookies } from 'react-cookie';
14
8
 
15
9
  import { Toast } from '@plone/volto/components';
16
10
  import { Form } from '@plone/volto/components/manage/Form';
@@ -50,104 +44,56 @@ const messages = defineMessages({
50
44
  },
51
45
  });
52
46
 
53
- /**
54
- * PersonalPreferences class.
55
- * @class PersonalPreferences
56
- * @extends Component
57
- */
58
- class PersonalPreferences extends Component {
59
- /**
60
- * Property types.
61
- * @property {Object} propTypes Property types.
62
- * @static
63
- */
64
- static propTypes = {
65
- changeLanguage: PropTypes.func.isRequired,
66
- closeMenu: PropTypes.func.isRequired,
67
- };
68
-
69
- /**
70
- * Constructor
71
- * @method constructor
72
- * @param {Object} props Component properties
73
- * @constructs PersonalPreferences
74
- */
75
- constructor(props) {
76
- super(props);
77
- this.onCancel = this.onCancel.bind(this);
78
- this.onSubmit = this.onSubmit.bind(this);
79
- }
80
-
81
- /**
82
- * Submit handler
83
- * @method onSubmit
84
- * @param {object} data Form data.
85
- * @returns {undefined}
86
- */
87
- onSubmit(data) {
47
+ const PersonalPreferences = (props) => {
48
+ const intl = useIntl();
49
+ const dispatch = useDispatch();
50
+ const { closeMenu } = props;
51
+ const onSubmit = (data) => {
88
52
  let language = data.language || 'en';
89
53
  if (config.settings.supportedLanguages.includes(language)) {
90
54
  const langFileName = toGettextLang(language);
91
55
  import(
92
56
  /* @vite-ignore */ '@root/../locales/' + langFileName + '.json'
93
57
  ).then((locale) => {
94
- this.props.changeLanguage(language, locale.default);
58
+ dispatch(changeLanguage(language, locale.default));
95
59
  });
96
60
  }
97
- toast.success(
98
- <Toast success title={this.props.intl.formatMessage(messages.saved)} />,
99
- );
100
- this.props.closeMenu();
101
- }
102
-
103
- /**
104
- * Cancel handler
105
- * @method onCancel
106
- * @returns {undefined}
107
- */
108
- onCancel() {
109
- this.props.closeMenu();
110
- }
61
+ toast.success(<Toast success title={intl.formatMessage(messages.saved)} />);
62
+ closeMenu();
63
+ };
111
64
 
112
- /**
113
- * Render method.
114
- * @method render
115
- * @returns {string} Markup for the component.
116
- */
117
- render() {
118
- const { cookies } = this.props;
119
- return (
120
- <Form
121
- formData={{ language: cookies.get('I18N_LANGUAGE') || '' }}
122
- schema={{
123
- fieldsets: [
124
- {
125
- id: 'default',
126
- title: this.props.intl.formatMessage(messages.default),
127
- fields: ['language'],
128
- },
129
- ],
130
- properties: {
131
- language: {
132
- description: this.props.intl.formatMessage(
133
- messages.languageDescription,
134
- ),
135
- title: this.props.intl.formatMessage(messages.language),
136
- type: 'string',
137
- choices: map(keys(languages), (lang) => [lang, languages[lang]]),
138
- },
65
+ const onCancel = () => {
66
+ closeMenu();
67
+ };
68
+ const { cookies } = props;
69
+ return (
70
+ <Form
71
+ formData={{ language: cookies.get('I18N_LANGUAGE') || '' }}
72
+ schema={{
73
+ fieldsets: [
74
+ {
75
+ id: 'default',
76
+ title: intl.formatMessage(messages.default),
77
+ fields: ['language'],
78
+ },
79
+ ],
80
+ properties: {
81
+ language: {
82
+ description: intl.formatMessage(messages.languageDescription),
83
+ title: intl.formatMessage(messages.language),
84
+ type: 'string',
85
+ choices: map(keys(languages), (lang) => [lang, languages[lang]]),
139
86
  },
140
- required: [],
141
- }}
142
- onSubmit={this.onSubmit}
143
- onCancel={this.onCancel}
144
- />
145
- );
146
- }
147
- }
87
+ },
88
+ required: [],
89
+ }}
90
+ onSubmit={onSubmit}
91
+ onCancel={onCancel}
92
+ />
93
+ );
94
+ };
148
95
 
149
- export default compose(
150
- injectIntl,
151
- withCookies,
152
- connect(null, { changeLanguage }),
153
- )(PersonalPreferences);
96
+ PersonalPreferences.propTypes = {
97
+ closeMenu: PropTypes.func.isRequired,
98
+ };
99
+ export default compose(withCookies)(PersonalPreferences);