@plone/volto 18.0.0-alpha.41 → 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 (187) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/finalreleasechangelog.py +48 -0
  3. package/locales/ca/LC_MESSAGES/volto.po +39 -13
  4. package/locales/ca.json +1 -1
  5. package/locales/de/LC_MESSAGES/volto.po +40 -14
  6. package/locales/de.json +1 -1
  7. package/locales/en/LC_MESSAGES/volto.po +39 -13
  8. package/locales/en.json +1 -1
  9. package/locales/es/LC_MESSAGES/volto.po +40 -14
  10. package/locales/es.json +1 -1
  11. package/locales/eu/LC_MESSAGES/volto.po +40 -14
  12. package/locales/eu.json +1 -1
  13. package/locales/fi/LC_MESSAGES/volto.po +40 -14
  14. package/locales/fi.json +1 -1
  15. package/locales/fr/LC_MESSAGES/volto.po +40 -14
  16. package/locales/fr.json +1 -1
  17. package/locales/hi/LC_MESSAGES/volto.po +40 -14
  18. package/locales/hi.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +40 -14
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +39 -13
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +39 -13
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +39 -13
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +40 -14
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +39 -13
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +40 -14
  32. package/locales/zh_CN/LC_MESSAGES/volto.po +40 -14
  33. package/locales/zh_CN.json +1 -1
  34. package/package.json +5 -6
  35. package/razzle.config.js +3 -3
  36. package/src/components/index.js +0 -1
  37. package/src/components/manage/Actions/Actions.stories.jsx +138 -0
  38. package/src/components/manage/Add/Add.jsx +7 -4
  39. package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
  40. package/src/components/manage/Blocks/Block/BlocksForm.jsx +5 -0
  41. package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
  42. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
  43. package/src/components/manage/Blocks/Block/Order/Item.jsx +8 -2
  44. package/src/components/manage/Blocks/Block/Order/Order.jsx +2 -0
  45. package/src/components/manage/Blocks/Container/Data.jsx +10 -2
  46. package/src/components/manage/Blocks/Grid/View.jsx +3 -0
  47. package/src/components/manage/Blocks/Image/ImageSidebar.jsx +10 -2
  48. package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
  49. package/src/components/manage/Blocks/Listing/ListingData.jsx +10 -2
  50. package/src/components/manage/Blocks/Maps/MapsSidebar.jsx +3 -1
  51. package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +2 -0
  52. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +18 -2
  53. package/src/components/manage/Blocks/Search/components/SortOn.jsx +82 -55
  54. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +1 -1
  55. package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
  56. package/src/components/manage/Blocks/Teaser/Data.jsx +10 -2
  57. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
  58. package/src/components/manage/Blocks/ToC/Edit.jsx +36 -28
  59. package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
  60. package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
  61. package/src/components/manage/Blocks/Video/VideoSidebar.jsx +3 -1
  62. package/src/components/manage/Contents/Contents.jsx +4 -1
  63. package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
  64. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
  65. package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
  66. package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
  67. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
  68. package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
  69. package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
  70. package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -0
  71. package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
  72. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
  73. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
  74. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
  75. package/src/components/manage/Controlpanels/UndoControlpanel.jsx +3 -3
  76. package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +28 -12
  77. package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +12 -4
  78. package/src/components/manage/Display/Display.jsx +92 -148
  79. package/src/components/manage/Display/Display.stories.jsx +46 -0
  80. package/src/components/manage/Edit/Edit.jsx +2 -4
  81. package/src/components/manage/Form/Form.jsx +85 -20
  82. package/src/components/manage/Form/InlineForm.jsx +2 -4
  83. package/src/components/manage/Form/ModalForm.jsx +1 -1
  84. package/src/components/manage/History/History.jsx +1 -1
  85. package/src/components/manage/Pluggable/Pluggable.test.js +1 -1
  86. package/src/components/manage/Preferences/ChangePassword.jsx +94 -172
  87. package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
  88. package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
  89. package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
  90. package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
  91. package/src/components/manage/Toolbar/More.jsx +308 -399
  92. package/src/components/manage/Toolbar/Toolbar.jsx +1 -1
  93. package/src/components/manage/Widgets/ArrayWidget.jsx +2 -2
  94. package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
  95. package/src/components/manage/Widgets/ImageWidget.jsx +6 -5
  96. package/src/components/manage/Widgets/RecurrenceWidget/EndField.jsx +7 -1
  97. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +80 -31
  98. package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
  99. package/src/components/theme/Register/Register.jsx +70 -142
  100. package/src/components/theme/Register/Register.stories.jsx +49 -0
  101. package/src/components/theme/Search/Search.jsx +13 -5
  102. package/src/components/theme/Tags/Tags.jsx +19 -10
  103. package/src/components/theme/Tags/Tags.test.jsx +9 -11
  104. package/src/components/theme/View/AlbumView.jsx +122 -167
  105. package/src/components/theme/View/LinkView.jsx +4 -0
  106. package/src/components/theme/View/LinkView.test.jsx +2 -0
  107. package/src/components/theme/View/View.jsx +0 -13
  108. package/src/components/theme/View/View.test.jsx +0 -3
  109. package/src/config/ControlPanels.js +49 -43
  110. package/src/config/Widgets.jsx +1 -1
  111. package/src/config/config.test.js +1 -0
  112. package/src/config/index.js +23 -2
  113. package/src/config/slots.js +12 -0
  114. package/src/config/validation.ts +155 -0
  115. package/src/helpers/Blocks/Blocks.js +12 -7
  116. package/src/helpers/Blocks/Blocks.test.js +15 -0
  117. package/src/helpers/Blocks/cloneBlocks.ts +1 -1
  118. package/src/helpers/Extensions/withBlockExtensions.jsx +1 -1
  119. package/src/helpers/FormValidation/FormValidation.jsx +128 -172
  120. package/src/helpers/FormValidation/FormValidation.test.js +836 -8
  121. package/src/helpers/FormValidation/validators.ts +203 -0
  122. package/src/helpers/MessageLabels/MessageLabels.js +28 -0
  123. package/src/helpers/Url/Url.test.js +19 -6
  124. package/src/helpers/Url/urlRegex.js +1 -1
  125. package/src/helpers/User/User.js +1 -1
  126. package/src/helpers/index.js +2 -0
  127. package/src/hooks/client/useClient.js +1 -1
  128. package/src/middleware/api.js +4 -2
  129. package/src/middleware/index.js +1 -0
  130. package/src/middleware/userSessionReset.js +46 -0
  131. package/src/store.js +2 -0
  132. package/test-setup-config.jsx +10 -0
  133. package/theme/themes/default/modules/embed.variables +1 -1
  134. package/theme/themes/pastanaga/collections/form.overrides +34 -0
  135. package/theme/themes/pastanaga/extras/blocks.less +6 -0
  136. package/theme/themes/pastanaga/extras/sidebar.less +4 -0
  137. package/theme/themes/pastanaga/extras/toolbar.less +10 -3
  138. package/tsconfig.declarations.json +3 -2
  139. package/types/components/index.d.ts +0 -1
  140. package/types/components/manage/Actions/Actions.stories.d.ts +8 -0
  141. package/types/components/manage/Blocks/Block/Order/Order.d.ts +2 -1
  142. package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
  143. package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
  144. package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
  145. package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
  146. package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
  147. package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
  148. package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
  149. package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
  150. package/types/components/manage/Contents/index.d.ts +1 -1
  151. package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
  152. package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
  153. package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
  154. package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
  155. package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
  156. package/types/components/manage/Controlpanels/index.d.ts +4 -4
  157. package/types/components/manage/Display/Display.stories.d.ts +8 -0
  158. package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
  159. package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
  160. package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
  161. package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
  162. package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
  163. package/types/components/manage/Toolbar/More.d.ts +8 -5
  164. package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
  165. package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
  166. package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
  167. package/types/components/manage/Widgets/index.d.ts +1 -1
  168. package/types/components/theme/Register/Register.d.ts +2 -2
  169. package/types/components/theme/Register/Register.stories.d.ts +9 -0
  170. package/types/components/theme/Tags/Tags.d.ts +15 -7
  171. package/types/components/theme/View/AlbumView.d.ts +3 -17
  172. package/types/config/ControlPanels.d.ts +8 -0
  173. package/types/config/RichTextEditor/ToHTML.d.ts +1 -1
  174. package/types/config/Widgets.d.ts +3 -3
  175. package/types/config/slots.d.ts +21 -0
  176. package/types/config/validation.d.ts +3 -0
  177. package/types/helpers/Blocks/Blocks.d.ts +6 -0
  178. package/types/helpers/Extensions/withBlockExtensions.d.ts +1 -1
  179. package/types/helpers/FormValidation/FormValidation.d.ts +2 -0
  180. package/types/helpers/FormValidation/validators.d.ts +29 -0
  181. package/types/helpers/MessageLabels/MessageLabels.d.ts +36 -0
  182. package/types/helpers/User/User.d.ts +1 -1
  183. package/types/helpers/index.d.ts +2 -2
  184. package/types/middleware/index.d.ts +1 -0
  185. package/types/middleware/userSessionReset.d.ts +5 -0
  186. package/src/components/theme/SocialSharing/SocialSharing.jsx +0 -48
  187. package/src/components/theme/SocialSharing/SocialSharing.test.jsx +0 -14
@@ -12,6 +12,7 @@ import {
12
12
  FormValidation,
13
13
  getBlocksFieldname,
14
14
  getBlocksLayoutFieldname,
15
+ hasBlocksData,
15
16
  messages,
16
17
  } from '@plone/volto/helpers';
17
18
  import aheadSVG from '@plone/volto/icons/ahead.svg';
@@ -349,7 +350,7 @@ class Form extends Component {
349
350
 
350
351
  /**
351
352
  * If user clicks on input, the form will be not considered pristine
352
- * this will avoid onBlur effects without interraction with the form
353
+ * this will avoid onBlur effects without interaction with the form
353
354
  * @param {Object} e event
354
355
  */
355
356
  onClickInput(e) {
@@ -527,30 +528,92 @@ class Form extends Component {
527
528
  })
528
529
  : {};
529
530
 
530
- if (keys(errors).length > 0) {
531
+ let blocksErrors = {};
532
+
533
+ if (hasBlocksData(formData)) {
534
+ // Validate blocks
535
+ const blocks = this.state.formData[getBlocksFieldname(formData)];
536
+ const blocksLayout =
537
+ this.state.formData[getBlocksLayoutFieldname(formData)];
538
+ const defaultSchema = {
539
+ properties: {},
540
+ fieldsets: [],
541
+ required: [],
542
+ };
543
+ blocksLayout.items.forEach((block) => {
544
+ let blockSchema =
545
+ config.blocks.blocksConfig[blocks[block]['@type']].blockSchema ||
546
+ defaultSchema;
547
+ if (typeof blockSchema === 'function') {
548
+ blockSchema = blockSchema({
549
+ intl: this.props.intl,
550
+ formData: blocks[block],
551
+ });
552
+ }
553
+ const blockErrors = FormValidation.validateFieldsPerFieldset({
554
+ schema: blockSchema,
555
+ formData: blocks[block],
556
+ formatMessage: this.props.intl.formatMessage,
557
+ });
558
+ if (keys(blockErrors).length > 0) {
559
+ blocksErrors = {
560
+ ...blocksErrors,
561
+ [block]: { ...blockErrors },
562
+ };
563
+ }
564
+ });
565
+ }
566
+
567
+ if (keys(errors).length > 0 || keys(blocksErrors).length > 0) {
531
568
  const activeIndex = FormValidation.showFirstTabWithErrors({
532
569
  errors,
533
570
  schema: this.props.schema,
534
571
  });
535
- this.setState(
536
- {
537
- errors,
538
- activeIndex,
539
- },
540
- () => {
541
- Object.keys(errors).forEach((err) =>
542
- toast.error(
543
- <Toast
544
- error
545
- title={this.props.schema.properties[err].title || err}
546
- content={errors[err].join(', ')}
547
- />,
548
- ),
549
- );
572
+
573
+ this.setState({
574
+ errors: {
575
+ ...errors,
576
+ ...(!isEmpty(blocksErrors) && { blocks: blocksErrors }),
550
577
  },
551
- );
552
- // Changes the focus to the metadata tab in the sidebar if error
553
- this.props.setSidebarTab(0);
578
+ activeIndex,
579
+ });
580
+
581
+ if (keys(errors).length > 0) {
582
+ // Changes the focus to the metadata tab in the sidebar if error
583
+ Object.keys(errors).forEach((err) =>
584
+ toast.error(
585
+ <Toast
586
+ error
587
+ title={this.props.schema.properties[err].title || err}
588
+ content={errors[err].join(', ')}
589
+ />,
590
+ ),
591
+ );
592
+ this.props.setSidebarTab(0);
593
+ } else if (keys(blocksErrors).length > 0) {
594
+ const errorField = Object.entries(
595
+ Object.entries(blocksErrors)[0][1],
596
+ )[0][0];
597
+ const errorMessage = Object.entries(
598
+ Object.entries(blocksErrors)[0][1],
599
+ )[0][1];
600
+ toast.error(
601
+ <Toast
602
+ error
603
+ title={this.props.intl.formatMessage(
604
+ messages.blocksFieldsErrorTitle,
605
+ { errorField },
606
+ )}
607
+ content={errorMessage}
608
+ />,
609
+ );
610
+ this.props.setSidebarTab(1);
611
+ this.props.setUIState({
612
+ selected: Object.keys(blocksErrors)[0],
613
+ multiSelected: [],
614
+ hovered: null,
615
+ });
616
+ }
554
617
  } else {
555
618
  // Get only the values that have been modified (Edit forms), send all in case that
556
619
  // it's an add form
@@ -730,6 +793,8 @@ class Form extends Component {
730
793
  history={this.props.history}
731
794
  location={this.props.location}
732
795
  token={this.props.token}
796
+ errors={this.state.errors}
797
+ blocksErrors={this.state.errors.blocks}
733
798
  />
734
799
  {this.state.isClient &&
735
800
  this.state.sidebarMetadataIsAvailable &&
@@ -142,7 +142,6 @@ const InlineForm = (props) => {
142
142
  content={error.message}
143
143
  />
144
144
  )}
145
-
146
145
  <div id={`blockform-fieldset-${defaultFieldset.id}`}>
147
146
  <Segment className="form attached">
148
147
  {map(defaultFieldset.fields, (field, index) => (
@@ -157,7 +156,7 @@ const InlineForm = (props) => {
157
156
  onChangeField(id, value, itemInfo);
158
157
  }}
159
158
  key={field}
160
- error={errors[field]}
159
+ error={errors?.[block]?.[field] || {}}
161
160
  block={block}
162
161
  />
163
162
  ))}
@@ -166,7 +165,6 @@ const InlineForm = (props) => {
166
165
  )}
167
166
  </Segment>
168
167
  </div>
169
-
170
168
  {other.map((fieldset, index) => (
171
169
  <Accordion fluid styled className="form" key={fieldset.id}>
172
170
  <div key={fieldset.id} id={`blockform-fieldset-${fieldset.id}`}>
@@ -199,7 +197,7 @@ const InlineForm = (props) => {
199
197
  onChangeField(id, value);
200
198
  }}
201
199
  key={field}
202
- error={errors[field]}
200
+ error={errors?.[block]?.[field] || {}}
203
201
  block={block}
204
202
  />
205
203
  ))}
@@ -137,7 +137,7 @@ class ModalForm extends Component {
137
137
 
138
138
  /**
139
139
  * If user clicks on input, the form will be not considered pristine
140
- * this will avoid onBlur effects without interraction with the form
140
+ * this will avoid onBlur effects without interaction with the form
141
141
  * @param {Object} e event
142
142
  */
143
143
  onClickInput(e) {
@@ -345,7 +345,7 @@ export default compose(
345
345
  asyncConnect([
346
346
  {
347
347
  key: 'actions',
348
- // Dispatch async/await to make the operation syncronous, otherwise it returns
348
+ // Dispatch async/await to make the operation synchronous, otherwise it returns
349
349
  // before the promise is resolved
350
350
  promise: async ({ location, store: { dispatch } }) =>
351
351
  await dispatch(listActions(getBaseUrl(location.pathname))),
@@ -31,7 +31,7 @@ describe('<Pluggable />', () => {
31
31
  expect(container).toMatchSnapshot();
32
32
  });
33
33
 
34
- it('Works with an empy Plug', () => {
34
+ it('Works with an empty Plug', () => {
35
35
  const { container } = render(
36
36
  <PluggablesProvider>
37
37
  <Pluggable name="test" />
@@ -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
+ };