@plone/volto 17.0.0-alpha.26 → 17.0.0-alpha.28
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/.eslintrc +26 -3
- package/.yarn/install-state.gz +0 -0
- package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +541 -0
- package/.yarn/releases/yarn-3.6.3.cjs +874 -0
- package/CHANGELOG.md +60 -0
- package/addon-registry.js +10 -1
- package/create-addons-loader.js +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +57 -31
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +58 -32
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +57 -31
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +65 -39
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +57 -31
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +57 -31
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +57 -31
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +57 -31
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +57 -31
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +57 -31
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +57 -31
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +57 -31
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +57 -31
- package/locales/ro.json +1 -1
- package/locales/volto.pot +62 -32
- package/locales/zh_CN/LC_MESSAGES/volto.po +57 -31
- package/locales/zh_CN.json +1 -1
- package/package.json +35 -26
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +2 -1
- package/packages/volto-slate/src/blocks/Text/index.js +0 -5
- package/packages/volto-slate/src/editor/plugins/Link/render.jsx +5 -6
- package/packages/volto-slate/src/editor/render.jsx +11 -1
- package/razzle.config.js +4 -6
- package/src/components/index.js +194 -194
- package/src/components/manage/Add/Add.jsx +7 -8
- package/src/components/manage/Blocks/Block/Settings.test.jsx +17 -15
- package/src/components/manage/Blocks/HTML/Edit.jsx +8 -8
- package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +30 -25
- package/src/components/manage/Blocks/Listing/ListingBody.jsx +6 -4
- package/src/components/manage/Blocks/Maps/Edit.test.jsx +1 -2
- package/src/components/manage/Blocks/Maps/View.test.jsx +1 -2
- package/src/components/manage/Blocks/Search/components/Facets.jsx +2 -3
- package/src/components/manage/Blocks/Search/components/FilterList.jsx +4 -6
- package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +2 -9
- package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +3 -0
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +8 -6
- package/src/components/manage/Blocks/Search/schema.js +13 -13
- package/src/components/manage/Blocks/Table/Cell.jsx +2 -3
- package/src/components/manage/Blocks/Text/Edit.jsx +2 -3
- package/src/components/manage/Blocks/Title/View.jsx +4 -37
- package/src/components/manage/Blocks/ToC/View.jsx +1 -0
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +3 -2
- package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +3 -2
- package/src/components/manage/Contents/Contents.jsx +252 -114
- package/src/components/manage/Contents/ContentsPropertiesModal.jsx +90 -154
- package/src/components/manage/Contents/ContentsRenameModal.jsx +88 -139
- package/src/components/manage/Contents/ContentsRenameModal.stories.jsx +61 -0
- package/src/components/manage/Contents/ContentsTagsModal.jsx +83 -130
- package/src/components/manage/Contents/ContentsTagsModal.stories.jsx +68 -0
- package/src/components/manage/Contents/ContentsUploadModal.jsx +1 -2
- package/src/components/manage/Contents/ContentsWorkflowModal.jsx +87 -154
- package/src/components/manage/Controlpanels/Aliases.jsx +4 -12
- package/src/components/manage/Controlpanels/Rules/AddRule.jsx +2 -9
- package/src/components/manage/Controlpanels/UndoControlpanel.jsx +6 -9
- package/src/components/manage/Form/BlockDataForm.test.jsx +17 -15
- package/src/components/manage/Form/Form.jsx +2 -3
- package/src/components/manage/Form/InlineForm.test.jsx +16 -14
- package/src/components/manage/LockingToastsFactory/LockingToastsFactory.jsx +1 -2
- package/src/components/manage/Sharing/Sharing.jsx +7 -0
- package/src/components/manage/Sidebar/Sidebar.jsx +139 -220
- package/src/components/manage/Toolbar/More.jsx +12 -12
- package/src/components/manage/Toolbar/PersonalTools.jsx +97 -155
- package/src/components/manage/Toolbar/Toolbar.jsx +2 -2
- package/src/components/manage/UniversalLink/UniversalLink.test.jsx +2 -1
- package/src/components/manage/Widgets/AlignWidget.jsx +2 -4
- package/src/components/manage/Widgets/ColorPickerWidget.test.jsx +9 -7
- package/src/components/manage/Widgets/DatetimeWidget.jsx +2 -8
- package/src/components/manage/Widgets/IdWidget.jsx +1 -2
- package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +2 -9
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +2 -9
- package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +4 -4
- package/src/components/manage/Widgets/SchemaWidget.jsx +6 -9
- package/src/components/manage/Widgets/WysiwygWidget.jsx +2 -9
- package/src/components/theme/Comments/Comments.jsx +3 -10
- package/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +4 -0
- package/src/components/theme/Login/Login.jsx +1 -2
- package/src/components/theme/PasswordReset/PasswordReset.jsx +1 -2
- package/src/components/theme/PreviewImage/PreviewImage.jsx +10 -5
- package/src/components/theme/PreviewImage/PreviewImage.test.js +17 -0
- package/src/components/theme/Register/Register.jsx +2 -4
- package/src/components/theme/TsTest/TsTest.test.tsx +11 -0
- package/src/components/theme/TsTest/TsTest.tsx +15 -0
- package/src/components/theme/View/AlbumView.jsx +3 -2
- package/src/components/theme/Widgets/ImageWidget.stories.jsx +1 -2
- package/src/config/Loadables.jsx +1 -1
- package/src/config/RichTextEditor/Blocks.jsx +2 -3
- package/src/config/RichTextEditor/Plugins.jsx +2 -3
- package/src/config/RichTextEditor/ToHTML.jsx +12 -10
- package/src/config/RichTextEditor/index.js +2 -3
- package/src/config/Views.jsx +5 -5
- package/src/express-middleware/ok.js +1 -1
- package/src/helpers/Blocks/Blocks.js +4 -6
- package/src/helpers/Blocks/Blocks.test.js +35 -35
- package/src/helpers/Extensions/withBlockSchemaEnhancer.js +48 -50
- package/src/helpers/FormValidation/FormValidation.js +7 -6
- package/src/helpers/Html/Html.jsx +2 -8
- package/src/helpers/Loadable/__mocks__/Loadable.js +18 -18
- package/src/helpers/MessageLabels/MessageLabels.js +2 -3
- package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +2 -3
- package/src/helpers/Utils/Utils.js +10 -0
- package/src/helpers/Utils/Utils.test.js +13 -0
- package/src/helpers/index.js +1 -0
- package/src/hooks/index.js +1 -1
- package/src/middleware/api.js +194 -190
- package/src/middleware/blacklistRoutes.js +25 -22
- package/src/middleware/storeProtectLoadUtils.js +61 -62
- package/src/middleware/storeProtectLoadUtils.test.js +47 -43
- package/src/reducers/content/content.test.js +4 -4
- package/src/reducers/navigation/navigation.js +5 -5
- package/src/reducers/navigation/navigation.test.js +30 -0
- package/src/registry.js +2 -2
- package/src/storybook.jsx +24 -38
- package/theme/themes/pastanaga/collections/menu.overrides +3 -2
- package/theme/themes/pastanaga/elements/container.overrides +5 -2
- package/theme/themes/pastanaga/elements/input.overrides +1 -1
- package/theme/themes/pastanaga/elements/step.overrides +2 -1
- package/theme/themes/pastanaga/extras/blocks.less +20 -14
- package/theme/themes/pastanaga/extras/color-picker-widget.less +1 -1
- package/theme/themes/pastanaga/extras/contents.less +5 -1
- package/theme/themes/pastanaga/extras/draftjs.less +4 -4
- package/theme/themes/pastanaga/extras/grid.less +5 -4
- package/theme/themes/pastanaga/extras/main.less +6 -6
- package/theme/themes/pastanaga/extras/react-dates-overrides.less +4 -2
- package/theme/themes/pastanaga/extras/search.less +2 -2
- package/theme/themes/pastanaga/extras/sidebar.less +5 -4
- package/theme/themes/pastanaga/extras/time-picker-overrides.less +5 -3
- package/theme/themes/pastanaga/extras/toolbar.less +6 -2
- package/theme/themes/pastanaga/extras/userscontrolpanel.less +17 -9
- package/theme/themes/pastanaga/extras/widgets.less +1 -1
- package/theme/themes/pastanaga/modules/rating.overrides +2 -1
- package/theme/themes/pastanaga-cms-ui/elements/container.overrides +2 -1
- package/theme/themes/pastanaga-cms-ui/extras/cms-ui.elements.container.less +6 -2
- package/theme/themes/pastanaga-cms-ui/extras/cms-ui.site.less +2 -2
- package/tsconfig.json +33 -0
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
* PersonalTools container.
|
|
3
|
-
* @module components/manage/Toolbar/PersonalTools
|
|
4
|
-
*/
|
|
5
|
-
import React, { Component } from 'react';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
6
2
|
import PropTypes from 'prop-types';
|
|
7
|
-
import {
|
|
8
|
-
import { Link } from 'react-router-dom';
|
|
3
|
+
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
4
|
+
import { Link, useLocation } from 'react-router-dom';
|
|
9
5
|
import jwtDecode from 'jwt-decode';
|
|
10
6
|
import cx from 'classnames';
|
|
11
|
-
import { FormattedMessage,
|
|
7
|
+
import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
|
|
8
|
+
|
|
12
9
|
import { Icon } from '@plone/volto/components';
|
|
13
10
|
import { getUser } from '@plone/volto/actions';
|
|
14
11
|
import { Pluggable } from '@plone/volto/components/manage/Pluggable';
|
|
@@ -17,12 +14,8 @@ import {
|
|
|
17
14
|
getBaseUrl,
|
|
18
15
|
userHasRoles,
|
|
19
16
|
} from '@plone/volto/helpers';
|
|
20
|
-
import { withRouter } from 'react-router-dom';
|
|
21
|
-
import { compose } from 'redux';
|
|
22
|
-
|
|
23
17
|
import logoutSVG from '@plone/volto/icons/log-out.svg';
|
|
24
18
|
import rightArrowSVG from '@plone/volto/icons/right-key.svg';
|
|
25
|
-
|
|
26
19
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
27
20
|
import cameraSVG from '@plone/volto/icons/camera.svg';
|
|
28
21
|
|
|
@@ -49,158 +42,107 @@ const messages = defineMessages({
|
|
|
49
42
|
},
|
|
50
43
|
});
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* @property {Object} propTypes Property types.
|
|
61
|
-
* @static
|
|
62
|
-
*/
|
|
63
|
-
static propTypes = {
|
|
64
|
-
user: PropTypes.shape({
|
|
65
|
-
fullname: PropTypes.string,
|
|
66
|
-
email: PropTypes.string,
|
|
67
|
-
home_page: PropTypes.string,
|
|
68
|
-
location: PropTypes.string,
|
|
69
|
-
}).isRequired,
|
|
70
|
-
userId: PropTypes.string.isRequired,
|
|
71
|
-
getUser: PropTypes.func.isRequired,
|
|
72
|
-
loadComponent: PropTypes.func.isRequired,
|
|
73
|
-
};
|
|
45
|
+
const PersonalTools = (props) => {
|
|
46
|
+
const dispatch = useDispatch();
|
|
47
|
+
const intl = useIntl();
|
|
48
|
+
const { pathname } = useLocation();
|
|
49
|
+
const [, setPushed] = useState(false);
|
|
50
|
+
const token = useSelector((state) => state.userSession.token, shallowEqual);
|
|
51
|
+
const user = useSelector((state) => state.users.user);
|
|
52
|
+
const userId = token ? jwtDecode(token).sub : '';
|
|
74
53
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
dispatch(getUser(userId));
|
|
56
|
+
}, [dispatch, userId]);
|
|
78
57
|
|
|
79
|
-
push = (selector) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}));
|
|
83
|
-
this.props.loadComponent(selector);
|
|
58
|
+
const push = (selector) => {
|
|
59
|
+
setPushed(true);
|
|
60
|
+
props.loadComponent(selector);
|
|
84
61
|
};
|
|
85
62
|
|
|
86
|
-
pull = () => {
|
|
87
|
-
|
|
63
|
+
const pull = () => {
|
|
64
|
+
props.unloadComponent();
|
|
88
65
|
};
|
|
89
66
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
className={cx('personal-tools pastanaga-menu', {
|
|
70
|
+
'has-inner-actions': props.hasActions,
|
|
71
|
+
})}
|
|
72
|
+
style={{
|
|
73
|
+
flex: props.theToolbar.current
|
|
74
|
+
? `0 0 ${props.theToolbar.current.getBoundingClientRect().width}px`
|
|
75
|
+
: null,
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
<header className="header">
|
|
79
|
+
<button className="back" onClick={pull}>
|
|
80
|
+
<Icon
|
|
81
|
+
name={backSVG}
|
|
82
|
+
size="30px"
|
|
83
|
+
title={intl.formatMessage(messages.back)}
|
|
84
|
+
/>
|
|
85
|
+
</button>
|
|
86
|
+
<div className="vertical divider" />
|
|
87
|
+
<h2>{user.fullname ? user.fullname : user.username}</h2>
|
|
88
|
+
<Link id="toolbar-logout" to={`${getBaseUrl(pathname)}/logout`}>
|
|
89
|
+
<Icon
|
|
90
|
+
className="logout"
|
|
91
|
+
name={logoutSVG}
|
|
92
|
+
size="30px"
|
|
93
|
+
title={intl.formatMessage(messages.logout)}
|
|
94
|
+
/>
|
|
95
|
+
</Link>
|
|
96
|
+
</header>
|
|
97
|
+
<div className={cx('avatar', { default: !user.portrait })}>
|
|
98
|
+
{user.portrait ? (
|
|
99
|
+
<img
|
|
100
|
+
src={flattenToAppURL(user.portrait)}
|
|
101
|
+
alt={intl.formatMessage(messages.userAvatar)}
|
|
102
|
+
/>
|
|
103
|
+
) : (
|
|
104
|
+
<Icon name={cameraSVG} size="96px" />
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
{/* <Stats /> Maybe we can find a good fit in the future for this visual element */}
|
|
108
|
+
<div className="pastanaga-menu-list">
|
|
109
|
+
{/* This (probably also) should be a Component by itself*/}
|
|
110
|
+
<ul>
|
|
111
|
+
<li>
|
|
112
|
+
<Link
|
|
113
|
+
id={intl.formatMessage(messages.profile)}
|
|
114
|
+
to="/personal-information"
|
|
115
|
+
>
|
|
116
|
+
<FormattedMessage id="Profile" defaultMessage="Profile" />
|
|
117
|
+
<Icon name={rightArrowSVG} size="24px" />
|
|
118
|
+
</Link>
|
|
119
|
+
</li>
|
|
120
|
+
<li>
|
|
121
|
+
<button
|
|
122
|
+
aria-label={intl.formatMessage(messages.preferences)}
|
|
123
|
+
onClick={() => push('preferences')}
|
|
124
|
+
>
|
|
125
|
+
<FormattedMessage id="Preferences" defaultMessage="Preferences" />
|
|
126
|
+
<Icon name={rightArrowSVG} size="24px" />
|
|
127
|
+
</button>
|
|
128
|
+
</li>
|
|
129
|
+
|
|
130
|
+
{userHasRoles(user, ['Site Administrator', 'Manager']) && (
|
|
149
131
|
<li>
|
|
150
|
-
<Link
|
|
151
|
-
id=
|
|
152
|
-
to="/personal-information"
|
|
153
|
-
>
|
|
154
|
-
<FormattedMessage id="Profile" defaultMessage="Profile" />
|
|
132
|
+
<Link to="/controlpanel">
|
|
133
|
+
<FormattedMessage id="Site Setup" defaultMessage="Site Setup" />
|
|
155
134
|
<Icon name={rightArrowSVG} size="24px" />
|
|
156
135
|
</Link>
|
|
157
136
|
</li>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
onClick={() => this.push('preferences')}
|
|
162
|
-
>
|
|
163
|
-
<FormattedMessage
|
|
164
|
-
id="Preferences"
|
|
165
|
-
defaultMessage="Preferences"
|
|
166
|
-
/>
|
|
167
|
-
<Icon name={rightArrowSVG} size="24px" />
|
|
168
|
-
</button>
|
|
169
|
-
</li>
|
|
170
|
-
|
|
171
|
-
{userHasRoles(this.props.user, [
|
|
172
|
-
'Site Administrator',
|
|
173
|
-
'Manager',
|
|
174
|
-
]) && (
|
|
175
|
-
<li>
|
|
176
|
-
<Link to="/controlpanel">
|
|
177
|
-
<FormattedMessage
|
|
178
|
-
id="Site Setup"
|
|
179
|
-
defaultMessage="Site Setup"
|
|
180
|
-
/>
|
|
181
|
-
<Icon name={rightArrowSVG} size="24px" />
|
|
182
|
-
</Link>
|
|
183
|
-
</li>
|
|
184
|
-
)}
|
|
185
|
-
<Pluggable name="toolbar-user-menu" />
|
|
186
|
-
</ul>
|
|
187
|
-
</div>
|
|
137
|
+
)}
|
|
138
|
+
<Pluggable name="toolbar-user-menu" />
|
|
139
|
+
</ul>
|
|
188
140
|
</div>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
192
144
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
(state, props) => ({
|
|
198
|
-
pathname: props.location.pathname,
|
|
199
|
-
user: state.users.user,
|
|
200
|
-
userId: state.userSession.token
|
|
201
|
-
? jwtDecode(state.userSession.token).sub
|
|
202
|
-
: '',
|
|
203
|
-
}),
|
|
204
|
-
{ getUser },
|
|
205
|
-
),
|
|
206
|
-
)(PersonalTools);
|
|
145
|
+
PersonalTools.propTypes = {
|
|
146
|
+
loadComponent: PropTypes.func.isRequired,
|
|
147
|
+
};
|
|
148
|
+
export default PersonalTools;
|
|
@@ -591,8 +591,8 @@ class Toolbar extends Component {
|
|
|
591
591
|
messages.shrinkToolbar,
|
|
592
592
|
)}
|
|
593
593
|
className={cx({
|
|
594
|
-
[this.props.content?.review_state]:
|
|
595
|
-
?.review_state,
|
|
594
|
+
[this.props.content?.review_state]:
|
|
595
|
+
this.props.content?.review_state,
|
|
596
596
|
})}
|
|
597
597
|
onClick={this.handleShrink}
|
|
598
598
|
/>
|
|
@@ -158,7 +158,8 @@ describe('UniversalLink', () => {
|
|
|
158
158
|
});
|
|
159
159
|
|
|
160
160
|
it('UniversalLink renders external link where link is blacklisted', () => {
|
|
161
|
-
const notInEN =
|
|
161
|
+
const notInEN =
|
|
162
|
+
/^(?!.*(#|\/en|\/static|\/controlpanel|\/cypress|\/login|\/logout|\/contact-form)).*$/;
|
|
162
163
|
config.settings.externalRoutes = [
|
|
163
164
|
{
|
|
164
165
|
match: {
|
|
@@ -47,10 +47,8 @@ export const defaultActionsInfo = ({ intl }) => ({
|
|
|
47
47
|
const AlignWidget = (props) => {
|
|
48
48
|
const intl = useIntl();
|
|
49
49
|
|
|
50
|
-
const {
|
|
51
|
-
|
|
52
|
-
actionsInfoMap,
|
|
53
|
-
} = props;
|
|
50
|
+
const { actions = ['left', 'right', 'center', 'full'], actionsInfoMap } =
|
|
51
|
+
props;
|
|
54
52
|
|
|
55
53
|
const actionsInfo = {
|
|
56
54
|
...defaultActionsInfo({ intl }),
|
|
@@ -7,14 +7,16 @@ import ColorPickerWidget from './ColorPickerWidget';
|
|
|
7
7
|
|
|
8
8
|
const mockStore = configureStore();
|
|
9
9
|
|
|
10
|
-
const withStateManagement =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
setValue(value);
|
|
14
|
-
|
|
10
|
+
const withStateManagement =
|
|
11
|
+
(Component) =>
|
|
12
|
+
({ ...props }) => {
|
|
13
|
+
const [value, setValue] = React.useState(props.value || null);
|
|
14
|
+
const onChange = (id, value) => {
|
|
15
|
+
setValue(value);
|
|
16
|
+
};
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
+
return <Component {...props} onChange={onChange} value={value} />;
|
|
19
|
+
};
|
|
18
20
|
|
|
19
21
|
describe('ColorPickerWidget', () => {
|
|
20
22
|
const COLORS = [
|
|
@@ -179,14 +179,8 @@ export class DatetimeWidgetComponent extends Component {
|
|
|
179
179
|
onFocusChange = ({ focused }) => this.setState({ focused });
|
|
180
180
|
|
|
181
181
|
render() {
|
|
182
|
-
const {
|
|
183
|
-
|
|
184
|
-
resettable,
|
|
185
|
-
intl,
|
|
186
|
-
reactDates,
|
|
187
|
-
widgetOptions,
|
|
188
|
-
lang,
|
|
189
|
-
} = this.props;
|
|
182
|
+
const { id, resettable, intl, reactDates, widgetOptions, lang } =
|
|
183
|
+
this.props;
|
|
190
184
|
const noPastDates =
|
|
191
185
|
this.props.noPastDates || widgetOptions?.pattern_options?.noPastDates;
|
|
192
186
|
const moment = this.props.moment.default;
|
|
@@ -21,8 +21,7 @@ const messages = defineMessages({
|
|
|
21
21
|
defaultMessage: "This is a reserved name and can't be used",
|
|
22
22
|
},
|
|
23
23
|
invalidCharacters: {
|
|
24
|
-
id:
|
|
25
|
-
'Only lowercase letters (a-z) without accents, numbers (0-9), and the characters "-", "_", and "." are allowed.',
|
|
24
|
+
id: 'Only lowercase letters (a-z) without accents, numbers (0-9), and the characters "-", "_", and "." are allowed.',
|
|
26
25
|
defaultMessage:
|
|
27
26
|
'Only lowercase letters (a-z) without accents, numbers (0-9), and the characters "-", "_", and "." are allowed.',
|
|
28
27
|
},
|
|
@@ -312,15 +312,8 @@ export class ObjectBrowserWidgetComponent extends Component {
|
|
|
312
312
|
* @returns {string} Markup for the component.
|
|
313
313
|
*/
|
|
314
314
|
render() {
|
|
315
|
-
const {
|
|
316
|
-
|
|
317
|
-
description,
|
|
318
|
-
fieldSet,
|
|
319
|
-
value,
|
|
320
|
-
mode,
|
|
321
|
-
onChange,
|
|
322
|
-
isDisabled,
|
|
323
|
-
} = this.props;
|
|
315
|
+
const { id, description, fieldSet, value, mode, onChange, isDisabled } =
|
|
316
|
+
this.props;
|
|
324
317
|
|
|
325
318
|
let items = compact(!isArray(value) && value ? [value] : value || []);
|
|
326
319
|
|
|
@@ -734,15 +734,8 @@ class RecurrenceWidget extends Component {
|
|
|
734
734
|
render() {
|
|
735
735
|
const { open, dimmer, rruleSet, formValues, RRULE_LANGUAGE } = this.state;
|
|
736
736
|
|
|
737
|
-
const {
|
|
738
|
-
|
|
739
|
-
title,
|
|
740
|
-
required,
|
|
741
|
-
description,
|
|
742
|
-
error,
|
|
743
|
-
fieldSet,
|
|
744
|
-
intl,
|
|
745
|
-
} = this.props;
|
|
737
|
+
const { id, title, required, description, error, fieldSet, intl } =
|
|
738
|
+
this.props;
|
|
746
739
|
|
|
747
740
|
return (
|
|
748
741
|
<Form.Field
|
|
@@ -490,9 +490,8 @@ class SchemaWidget extends Component {
|
|
|
490
490
|
*/
|
|
491
491
|
onAddField(values) {
|
|
492
492
|
const fieldId = slugify(values.title);
|
|
493
|
-
const currentFieldsetFields =
|
|
494
|
-
this.state.currentFieldset
|
|
495
|
-
].fields;
|
|
493
|
+
const currentFieldsetFields =
|
|
494
|
+
this.props.value.fieldsets[this.state.currentFieldset].fields;
|
|
496
495
|
const hasChangeNote = currentFieldsetFields.indexOf('changeNote') > -1;
|
|
497
496
|
const newFieldsetFields = hasChangeNote
|
|
498
497
|
? [
|
|
@@ -698,9 +697,8 @@ class SchemaWidget extends Component {
|
|
|
698
697
|
const newParentFieldsetIndex = fieldsets.findIndex(
|
|
699
698
|
(field) => field.id === parentFieldSet,
|
|
700
699
|
);
|
|
701
|
-
const indexOfChangeNote =
|
|
702
|
-
newParentFieldsetIndex
|
|
703
|
-
].fields.indexOf('changeNote');
|
|
700
|
+
const indexOfChangeNote =
|
|
701
|
+
fieldsets[newParentFieldsetIndex].fields.indexOf('changeNote');
|
|
704
702
|
// remove from current fieldset
|
|
705
703
|
const fieldsetsWithoutField = [
|
|
706
704
|
...slice(fieldsets, 0, currentFieldset),
|
|
@@ -1363,9 +1361,8 @@ class SchemaWidget extends Component {
|
|
|
1363
1361
|
required:
|
|
1364
1362
|
this.props.value.required.indexOf(this.state.editField.id) !==
|
|
1365
1363
|
-1,
|
|
1366
|
-
parentFieldSet:
|
|
1367
|
-
this.state.currentFieldset
|
|
1368
|
-
].id,
|
|
1364
|
+
parentFieldSet:
|
|
1365
|
+
this.props.value.fieldsets[this.state.currentFieldset].id,
|
|
1369
1366
|
values: formatArrayToTextarea(
|
|
1370
1367
|
this.props.value.properties[this.state.editField.id],
|
|
1371
1368
|
),
|
|
@@ -261,15 +261,8 @@ class WysiwygWidgetComponent extends Component {
|
|
|
261
261
|
* @returns {string} Markup for the component.
|
|
262
262
|
*/
|
|
263
263
|
render() {
|
|
264
|
-
const {
|
|
265
|
-
|
|
266
|
-
title,
|
|
267
|
-
description,
|
|
268
|
-
required,
|
|
269
|
-
value,
|
|
270
|
-
error,
|
|
271
|
-
fieldSet,
|
|
272
|
-
} = this.props;
|
|
264
|
+
const { id, title, description, required, value, error, fieldSet } =
|
|
265
|
+
this.props;
|
|
273
266
|
|
|
274
267
|
if (__SERVER__) {
|
|
275
268
|
return (
|
|
@@ -31,8 +31,7 @@ const messages = defineMessages({
|
|
|
31
31
|
defaultMessage: 'Comments',
|
|
32
32
|
},
|
|
33
33
|
commentDescription: {
|
|
34
|
-
id:
|
|
35
|
-
'You can add a comment by filling out the form below. Plain text formatting.',
|
|
34
|
+
id: 'You can add a comment by filling out the form below. Plain text formatting.',
|
|
36
35
|
defaultMessage:
|
|
37
36
|
'You can add a comment by filling out the form below. Plain text formatting.',
|
|
38
37
|
},
|
|
@@ -113,14 +112,8 @@ const Comments = (props) => {
|
|
|
113
112
|
const [editText, seteditText] = useState(null);
|
|
114
113
|
const [replyTo, setreplyTo] = useState(null);
|
|
115
114
|
const [collapsedComments, setcollapsedComments] = useState({});
|
|
116
|
-
const {
|
|
117
|
-
|
|
118
|
-
next,
|
|
119
|
-
items_total,
|
|
120
|
-
permissions,
|
|
121
|
-
addRequest,
|
|
122
|
-
deleteRequest,
|
|
123
|
-
} = useComments();
|
|
115
|
+
const { items, next, items_total, permissions, addRequest, deleteRequest } =
|
|
116
|
+
useComments();
|
|
124
117
|
|
|
125
118
|
const prevpathname = usePrevious(pathname);
|
|
126
119
|
|
|
@@ -83,6 +83,10 @@ const ContentMetadataTags = (props) => {
|
|
|
83
83
|
<>
|
|
84
84
|
<Helmet>
|
|
85
85
|
<title>{getTitle()?.replace(/\u00AD/g, '')}</title>
|
|
86
|
+
<link
|
|
87
|
+
rel="canonical"
|
|
88
|
+
href={seo_canonical_url || toPublicURL(props.content['@id'])}
|
|
89
|
+
/>
|
|
86
90
|
<meta name="description" content={seo_description || description} />
|
|
87
91
|
<meta
|
|
88
92
|
property="og:title"
|
|
@@ -51,8 +51,7 @@ const messages = defineMessages({
|
|
|
51
51
|
defaultMessage: 'Login Failed',
|
|
52
52
|
},
|
|
53
53
|
loginFailedContent: {
|
|
54
|
-
id:
|
|
55
|
-
'Both email address and password are case sensitive, check that caps lock is not enabled.',
|
|
54
|
+
id: 'Both email address and password are case sensitive, check that caps lock is not enabled.',
|
|
56
55
|
defaultMessage:
|
|
57
56
|
'Both email address and password are case sensitive, check that caps lock is not enabled.',
|
|
58
57
|
},
|
|
@@ -79,8 +79,7 @@ const messages = defineMessages({
|
|
|
79
79
|
defaultMessage: 'Account activation completed',
|
|
80
80
|
},
|
|
81
81
|
successRedirectToLoginBody: {
|
|
82
|
-
id:
|
|
83
|
-
'Your password has been set successfully. You may now {link} with your new password.',
|
|
82
|
+
id: 'Your password has been set successfully. You may now {link} with your new password.',
|
|
84
83
|
defaultMessage:
|
|
85
84
|
'Your password has been set successfully. You may now {link} with your new password.',
|
|
86
85
|
},
|
|
@@ -7,13 +7,17 @@ import DefaultImageSVG from '@plone/volto/components/manage/Blocks/Listing/defau
|
|
|
7
7
|
/**
|
|
8
8
|
* Renders a preview image for a catalog brain result item.
|
|
9
9
|
*/
|
|
10
|
-
function PreviewImage({ item, alt, ...rest }) {
|
|
10
|
+
function PreviewImage({ item, alt, image_field, showDefault = true, ...rest }) {
|
|
11
11
|
const Image = config.getComponent({ name: 'Image' }).component;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const image = (
|
|
14
|
+
<Image item={item} image_field={image_field} alt={alt} {...rest} />
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
if (!image && !showDefault) return null;
|
|
18
|
+
|
|
19
|
+
if (image) {
|
|
20
|
+
return image;
|
|
17
21
|
} else {
|
|
18
22
|
return (
|
|
19
23
|
<img
|
|
@@ -38,6 +42,7 @@ PreviewImage.propTypes = {
|
|
|
38
42
|
title: PropTypes.string.isRequired,
|
|
39
43
|
image_field: PropTypes.string,
|
|
40
44
|
image_scales: PropTypes.object,
|
|
45
|
+
showDefault: PropTypes.bool,
|
|
41
46
|
}),
|
|
42
47
|
alt: PropTypes.string.isRequired,
|
|
43
48
|
};
|
|
@@ -109,4 +109,21 @@ describe('PreviewImage', () => {
|
|
|
109
109
|
const json = component.toJSON();
|
|
110
110
|
expect(json).toMatchSnapshot();
|
|
111
111
|
});
|
|
112
|
+
|
|
113
|
+
it('not renders a fallback image if showDefault prop is false', () => {
|
|
114
|
+
const item = {
|
|
115
|
+
title: 'Item title',
|
|
116
|
+
'@id': 'http://localhost:3000/something',
|
|
117
|
+
};
|
|
118
|
+
const component = renderer.create(
|
|
119
|
+
<PreviewImage
|
|
120
|
+
item={item}
|
|
121
|
+
className="extra"
|
|
122
|
+
showDefault={false}
|
|
123
|
+
alt={item.title}
|
|
124
|
+
/>,
|
|
125
|
+
);
|
|
126
|
+
const json = component.toJSON();
|
|
127
|
+
expect(json).toMatchSnapshot();
|
|
128
|
+
});
|
|
112
129
|
});
|
|
@@ -37,8 +37,7 @@ const messages = defineMessages({
|
|
|
37
37
|
defaultMessage: 'E-mail',
|
|
38
38
|
},
|
|
39
39
|
emailDescription: {
|
|
40
|
-
id:
|
|
41
|
-
'Enter an email address. This will be your login name. We respect your privacy, and will not give the address away to any third parties or expose it anywhere.',
|
|
40
|
+
id: 'Enter an email address. This will be your login name. We respect your privacy, and will not give the address away to any third parties or expose it anywhere.',
|
|
42
41
|
defaultMessage:
|
|
43
42
|
'Enter an email address. This will be your login name. We respect your privacy, and will not give the address away to any third parties or expose it anywhere.',
|
|
44
43
|
},
|
|
@@ -47,8 +46,7 @@ const messages = defineMessages({
|
|
|
47
46
|
defaultMessage: 'Account Registration Completed',
|
|
48
47
|
},
|
|
49
48
|
successRegisterCompletedBody: {
|
|
50
|
-
id:
|
|
51
|
-
'The registration process has been successful. Please check your e-mail inbox for information on how activate your account.',
|
|
49
|
+
id: 'The registration process has been successful. Please check your e-mail inbox for information on how activate your account.',
|
|
52
50
|
defaultMessage:
|
|
53
51
|
'The registration process has been successful. Please check your e-mail inbox for information on how activate your account.',
|
|
54
52
|
},
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import renderer from 'react-test-renderer';
|
|
2
|
+
import TsTest from './TsTest';
|
|
3
|
+
|
|
4
|
+
describe('Ts test component', () => {
|
|
5
|
+
test('Renders', () => {
|
|
6
|
+
const component = renderer.create(<TsTest text="Test a TS component" />);
|
|
7
|
+
const json = component.toJSON();
|
|
8
|
+
|
|
9
|
+
expect(json).toMatchSnapshot();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST COMPONENT: React TSX component
|
|
3
|
+
* Ensure successful implementation of TSX and validate the functionality with Jest tests
|
|
4
|
+
* Dependencies: jest (version 26.6.3), ts-jest (version ^26.4.2)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
type TestProps = {
|
|
8
|
+
text: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const TsTest = ({ text }: TestProps) => {
|
|
12
|
+
return <div>{text}</div>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default TsTest;
|