@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.
- package/CHANGELOG.md +114 -0
- package/finalreleasechangelog.py +48 -0
- package/locales/ca/LC_MESSAGES/volto.po +39 -13
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +40 -14
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +39 -13
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +40 -14
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +40 -14
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +40 -14
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +40 -14
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +40 -14
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +40 -14
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +39 -13
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +39 -13
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +39 -13
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +40 -14
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +39 -13
- package/locales/ro.json +1 -1
- package/locales/volto.pot +40 -14
- package/locales/zh_CN/LC_MESSAGES/volto.po +40 -14
- package/locales/zh_CN.json +1 -1
- package/package.json +5 -6
- package/razzle.config.js +3 -3
- package/src/components/index.js +0 -1
- package/src/components/manage/Actions/Actions.stories.jsx +138 -0
- package/src/components/manage/Add/Add.jsx +7 -4
- package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +5 -0
- package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
- package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
- package/src/components/manage/Blocks/Block/Order/Item.jsx +8 -2
- package/src/components/manage/Blocks/Block/Order/Order.jsx +2 -0
- package/src/components/manage/Blocks/Container/Data.jsx +10 -2
- package/src/components/manage/Blocks/Grid/View.jsx +3 -0
- package/src/components/manage/Blocks/Image/ImageSidebar.jsx +10 -2
- package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
- package/src/components/manage/Blocks/Listing/ListingData.jsx +10 -2
- package/src/components/manage/Blocks/Maps/MapsSidebar.jsx +3 -1
- package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +2 -0
- package/src/components/manage/Blocks/Search/SearchBlockView.jsx +18 -2
- package/src/components/manage/Blocks/Search/components/SortOn.jsx +82 -55
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +1 -1
- package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
- package/src/components/manage/Blocks/Teaser/Data.jsx +10 -2
- package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
- package/src/components/manage/Blocks/ToC/Edit.jsx +36 -28
- package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
- package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
- package/src/components/manage/Blocks/Video/VideoSidebar.jsx +3 -1
- package/src/components/manage/Contents/Contents.jsx +4 -1
- package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
- package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
- package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
- package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
- package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
- package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
- package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -0
- package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
- package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
- package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
- package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
- package/src/components/manage/Controlpanels/UndoControlpanel.jsx +3 -3
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +28 -12
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +12 -4
- package/src/components/manage/Display/Display.jsx +92 -148
- package/src/components/manage/Display/Display.stories.jsx +46 -0
- package/src/components/manage/Edit/Edit.jsx +2 -4
- package/src/components/manage/Form/Form.jsx +85 -20
- package/src/components/manage/Form/InlineForm.jsx +2 -4
- package/src/components/manage/Form/ModalForm.jsx +1 -1
- package/src/components/manage/History/History.jsx +1 -1
- package/src/components/manage/Pluggable/Pluggable.test.js +1 -1
- package/src/components/manage/Preferences/ChangePassword.jsx +94 -172
- package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
- package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
- package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
- package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
- package/src/components/manage/Toolbar/More.jsx +308 -399
- package/src/components/manage/Toolbar/Toolbar.jsx +1 -1
- package/src/components/manage/Widgets/ArrayWidget.jsx +2 -2
- package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
- package/src/components/manage/Widgets/ImageWidget.jsx +6 -5
- package/src/components/manage/Widgets/RecurrenceWidget/EndField.jsx +7 -1
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +80 -31
- package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
- package/src/components/theme/Register/Register.jsx +70 -142
- package/src/components/theme/Register/Register.stories.jsx +49 -0
- package/src/components/theme/Search/Search.jsx +13 -5
- package/src/components/theme/Tags/Tags.jsx +19 -10
- package/src/components/theme/Tags/Tags.test.jsx +9 -11
- package/src/components/theme/View/AlbumView.jsx +122 -167
- package/src/components/theme/View/LinkView.jsx +4 -0
- package/src/components/theme/View/LinkView.test.jsx +2 -0
- package/src/components/theme/View/View.jsx +0 -13
- package/src/components/theme/View/View.test.jsx +0 -3
- package/src/config/ControlPanels.js +49 -43
- package/src/config/Widgets.jsx +1 -1
- package/src/config/config.test.js +1 -0
- package/src/config/index.js +23 -2
- package/src/config/slots.js +12 -0
- package/src/config/validation.ts +155 -0
- package/src/helpers/Blocks/Blocks.js +12 -7
- package/src/helpers/Blocks/Blocks.test.js +15 -0
- package/src/helpers/Blocks/cloneBlocks.ts +1 -1
- package/src/helpers/Extensions/withBlockExtensions.jsx +1 -1
- package/src/helpers/FormValidation/FormValidation.jsx +128 -172
- package/src/helpers/FormValidation/FormValidation.test.js +836 -8
- package/src/helpers/FormValidation/validators.ts +203 -0
- package/src/helpers/MessageLabels/MessageLabels.js +28 -0
- package/src/helpers/Url/Url.test.js +19 -6
- package/src/helpers/Url/urlRegex.js +1 -1
- package/src/helpers/User/User.js +1 -1
- package/src/helpers/index.js +2 -0
- package/src/hooks/client/useClient.js +1 -1
- package/src/middleware/api.js +4 -2
- package/src/middleware/index.js +1 -0
- package/src/middleware/userSessionReset.js +46 -0
- package/src/store.js +2 -0
- package/test-setup-config.jsx +10 -0
- package/theme/themes/default/modules/embed.variables +1 -1
- package/theme/themes/pastanaga/collections/form.overrides +34 -0
- package/theme/themes/pastanaga/extras/blocks.less +6 -0
- package/theme/themes/pastanaga/extras/sidebar.less +4 -0
- package/theme/themes/pastanaga/extras/toolbar.less +10 -3
- package/tsconfig.declarations.json +3 -2
- package/types/components/index.d.ts +0 -1
- package/types/components/manage/Actions/Actions.stories.d.ts +8 -0
- package/types/components/manage/Blocks/Block/Order/Order.d.ts +2 -1
- package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
- package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
- package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
- package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
- package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
- package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
- package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
- package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
- package/types/components/manage/Contents/index.d.ts +1 -1
- package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
- package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
- package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
- package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
- package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
- package/types/components/manage/Controlpanels/index.d.ts +4 -4
- package/types/components/manage/Display/Display.stories.d.ts +8 -0
- package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
- package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
- package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
- package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
- package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
- package/types/components/manage/Toolbar/More.d.ts +8 -5
- package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
- package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
- package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
- package/types/components/manage/Widgets/index.d.ts +1 -1
- package/types/components/theme/Register/Register.d.ts +2 -2
- package/types/components/theme/Register/Register.stories.d.ts +9 -0
- package/types/components/theme/Tags/Tags.d.ts +15 -7
- package/types/components/theme/View/AlbumView.d.ts +3 -17
- package/types/config/ControlPanels.d.ts +8 -0
- package/types/config/RichTextEditor/ToHTML.d.ts +1 -1
- package/types/config/Widgets.d.ts +3 -3
- package/types/config/slots.d.ts +21 -0
- package/types/config/validation.d.ts +3 -0
- package/types/helpers/Blocks/Blocks.d.ts +6 -0
- package/types/helpers/Extensions/withBlockExtensions.d.ts +1 -1
- package/types/helpers/FormValidation/FormValidation.d.ts +2 -0
- package/types/helpers/FormValidation/validators.d.ts +29 -0
- package/types/helpers/MessageLabels/MessageLabels.d.ts +36 -0
- package/types/helpers/User/User.d.ts +1 -1
- package/types/helpers/index.d.ts +2 -2
- package/types/middleware/index.d.ts +1 -0
- package/types/middleware/userSessionReset.d.ts +5 -0
- package/src/components/theme/SocialSharing/SocialSharing.jsx +0 -48
- 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
|
|
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
|
-
|
|
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
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
|
|
553
|
-
|
|
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
|
|
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
|
|
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))),
|
|
@@ -1,25 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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 {
|
|
19
|
-
import {
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
* @returns {undefined}
|
|
140
|
-
*/
|
|
141
|
-
onCancel() {
|
|
142
|
-
this.props.history.goBack();
|
|
143
|
-
}
|
|
94
|
+
const onCancel = () => {
|
|
95
|
+
history.goBack();
|
|
96
|
+
};
|
|
144
97
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
|
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
|
+
};
|