@plone/volto 17.0.0-alpha.24 → 17.0.0-alpha.26
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/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +92 -4
- package/CONTRIBUTING.md +5 -1
- package/README.md +9 -7
- package/cypress/support/commands.js +12 -9
- package/cypress.config.js +1 -0
- package/locales/ca/LC_MESSAGES/volto.po +41 -15
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +41 -15
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +40 -14
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +69 -43
- 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 +41 -15
- package/locales/fr.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 +40 -14
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +41 -15
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +41 -15
- 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 +41 -15
- package/locales/ro.json +1 -1
- package/locales/volto.pot +41 -15
- package/locales/zh_CN/LC_MESSAGES/volto.po +41 -15
- package/locales/zh_CN.json +1 -1
- package/package.json +4 -4
- package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +90 -0
- package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +6 -0
- package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +6 -0
- package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +6 -0
- package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +10 -0
- package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +10 -0
- package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +30 -0
- package/packages/volto-slate/build/messages/src/elementEditor/messages.json +10 -0
- package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +6 -0
- package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +6 -0
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/editor/render.jsx +2 -3
- package/src/actions/index.js +4 -0
- package/src/actions/navroot/navroot.js +16 -0
- package/src/actions/navroot/navroot.test.js +15 -0
- package/src/actions/relations/relations.js +17 -0
- package/src/actions/site/site.js +16 -0
- package/src/actions/site/site.test.js +15 -0
- package/src/actions/userSession/userSession.js +17 -1
- package/src/components/manage/Blocks/Block/Settings.jsx +2 -0
- package/src/components/manage/Blocks/Block/Settings.test.jsx +90 -0
- package/src/components/manage/Blocks/Image/schema.js +5 -1
- package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +18 -11
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +42 -25
- package/src/components/manage/Blocks/ToC/View.jsx +75 -13
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +4 -13
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +44 -0
- package/src/components/manage/Contents/Contents.jsx +27 -0
- package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +65 -38
- package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +11 -9
- package/src/components/manage/Controlpanels/Relations/Relations.jsx +3 -3
- package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +8 -7
- package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +15 -9
- package/src/components/manage/Controlpanels/Rules/AddRule.jsx +1 -1
- package/src/components/manage/Controlpanels/Rules/EditRule.jsx +1 -1
- package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +95 -5
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +127 -99
- package/src/components/manage/Diff/DiffField.jsx +25 -1
- package/src/components/manage/Form/BlockDataForm.jsx +3 -2
- package/src/components/manage/Form/BlockDataForm.test.jsx +34 -2
- package/src/components/manage/LinksToItem/LinksToItem.jsx +1 -1
- package/src/components/manage/LinksToItem/LinksToItem.test.jsx +5 -2
- package/src/components/manage/Messages/Messages.jsx +32 -99
- package/src/components/manage/Messages/Messages.test.jsx +0 -1
- package/src/components/manage/Sharing/Sharing.jsx +50 -21
- package/src/components/manage/UniversalLink/UniversalLink.jsx +4 -6
- package/src/components/manage/Widgets/ArrayWidget.jsx +3 -1
- package/src/components/manage/Widgets/ArrayWidget.test.jsx +45 -1
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +1 -1
- package/src/components/manage/Widgets/RegistryImageWidget.jsx +210 -0
- package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +91 -0
- package/src/components/manage/Widgets/SelectWidget.jsx +15 -1
- package/src/components/manage/Widgets/SelectWidget.test.jsx +45 -1
- package/src/components/theme/Comments/Comment.stories.jsx +84 -0
- package/src/components/theme/Comments/Comments.jsx +273 -378
- package/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +37 -3
- package/src/components/theme/Login/Login.jsx +159 -241
- package/src/components/theme/Logo/Logo.Multilingual.test.jsx +131 -1
- package/src/components/theme/Logo/Logo.jsx +35 -29
- package/src/components/theme/Logo/Logo.test.jsx +135 -1
- package/src/components/theme/Logout/Logout.jsx +36 -83
- package/src/components/theme/Navigation/Navigation.jsx +86 -171
- package/src/components/theme/Search/SearchTags.jsx +30 -60
- package/src/components/theme/SearchWidget/SearchWidget.jsx +15 -3
- package/src/components/theme/SearchWidget/SearchWidget.test.jsx +8 -0
- package/src/components/theme/Sitemap/Sitemap.jsx +24 -13
- package/src/components/theme/Sitemap/Sitemap.test.jsx +23 -2
- package/src/components/theme/View/View.jsx +2 -0
- package/src/config/ControlPanels.js +0 -1
- package/src/config/Widgets.jsx +2 -0
- package/src/config/index.js +15 -3
- package/src/constants/ActionTypes.js +4 -0
- package/src/express-middleware/images.js +1 -0
- package/src/helpers/MessageLabels/MessageLabels.js +26 -4
- package/src/helpers/Site/index.js +21 -0
- package/src/helpers/index.js +1 -0
- package/src/reducers/index.js +4 -0
- package/src/reducers/navroot/navroot.js +79 -0
- package/src/reducers/navroot/navroot.test.js +110 -0
- package/src/reducers/relations/relations.js +74 -46
- package/src/reducers/site/site.js +51 -0
- package/src/reducers/site/site.test.js +67 -0
- package/src/reducers/userSession/userSession.js +15 -1
- package/src/server.jsx +9 -0
- package/test-setup-config.js +1 -0
- package/theme/themes/pastanaga/collections/form.overrides +46 -0
- package/theme/themes/pastanaga/elements/input.overrides +10 -0
- package/theme/themes/pastanaga/elements/label.overrides +10 -0
- package/theme/themes/pastanaga/extras/login.less +3 -0
- package/webpack-plugins/webpack-less-plugin.js +19 -0
- package/.gitignore~ +0 -71
- package/news/4547.breaking~ +0 -1
- package/package.json~ +0 -444
- package/src/config/index.js~ +0 -223
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
toPublicURL,
|
|
4
|
+
Helmet,
|
|
5
|
+
hasApiExpander,
|
|
6
|
+
getBaseUrl,
|
|
7
|
+
} from '@plone/volto/helpers';
|
|
8
|
+
import { getNavroot } from '@plone/volto/actions';
|
|
3
9
|
import config from '@plone/volto/registry';
|
|
10
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
4
11
|
|
|
5
12
|
const ContentMetadataTags = (props) => {
|
|
6
13
|
const {
|
|
@@ -14,6 +21,17 @@ const ContentMetadataTags = (props) => {
|
|
|
14
21
|
description,
|
|
15
22
|
} = props.content;
|
|
16
23
|
|
|
24
|
+
const dispatch = useDispatch();
|
|
25
|
+
const pathname = useSelector((state) => state.router.location.pathname);
|
|
26
|
+
const navroot = useSelector((state) => state.navroot?.data?.navroot);
|
|
27
|
+
const site = useSelector((state) => state.site?.data);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (pathname && !hasApiExpander('navroot', getBaseUrl(pathname))) {
|
|
31
|
+
dispatch(getNavroot(getBaseUrl(pathname)));
|
|
32
|
+
}
|
|
33
|
+
}, [dispatch, pathname]);
|
|
34
|
+
|
|
17
35
|
const getContentImageInfo = () => {
|
|
18
36
|
const { contentMetadataTagsImageField } = config.settings;
|
|
19
37
|
const image = props.content[contentMetadataTagsImageField];
|
|
@@ -45,10 +63,26 @@ const ContentMetadataTags = (props) => {
|
|
|
45
63
|
|
|
46
64
|
const contentImageInfo = getContentImageInfo();
|
|
47
65
|
|
|
66
|
+
const getTitle = () => {
|
|
67
|
+
const includeSiteTitle =
|
|
68
|
+
config?.settings?.siteTitleFormat?.includeSiteTitle || false;
|
|
69
|
+
const titleAndSiteTitleSeparator =
|
|
70
|
+
config?.settings?.titleAndSiteTitleSeparator || '-';
|
|
71
|
+
const navRootTitle = navroot?.title;
|
|
72
|
+
const siteRootTitle = site?.['plone.site_title'];
|
|
73
|
+
const titlePart = navRootTitle || siteRootTitle;
|
|
74
|
+
|
|
75
|
+
if (includeSiteTitle && titlePart && titlePart !== title) {
|
|
76
|
+
return seo_title || `${title} ${titleAndSiteTitleSeparator} ${titlePart}`;
|
|
77
|
+
} else {
|
|
78
|
+
return seo_title || title;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
48
82
|
return (
|
|
49
83
|
<>
|
|
50
84
|
<Helmet>
|
|
51
|
-
<title>{(
|
|
85
|
+
<title>{getTitle()?.replace(/\u00AD/g, '')}</title>
|
|
52
86
|
<meta name="description" content={seo_description || description} />
|
|
53
87
|
<meta
|
|
54
88
|
property="og:title"
|
|
@@ -1,14 +1,6 @@
|
|
|
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 } from 'react-router-dom';
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
3
|
+
import { Link, useHistory, useLocation } from 'react-router-dom';
|
|
12
4
|
import {
|
|
13
5
|
Container,
|
|
14
6
|
Button,
|
|
@@ -17,20 +9,18 @@ import {
|
|
|
17
9
|
Segment,
|
|
18
10
|
Grid,
|
|
19
11
|
} from 'semantic-ui-react';
|
|
20
|
-
import { FormattedMessage, defineMessages,
|
|
12
|
+
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
|
21
13
|
import qs from 'query-string';
|
|
22
|
-
import { withRouter } from 'react-router-dom';
|
|
23
14
|
|
|
15
|
+
import { Helmet } from '@plone/volto/helpers';
|
|
16
|
+
import config from '@plone/volto/registry';
|
|
24
17
|
import { Icon } from '@plone/volto/components';
|
|
25
|
-
import { login } from '@plone/volto/actions';
|
|
18
|
+
import { login, resetLoginRequest } from '@plone/volto/actions';
|
|
26
19
|
import { toast } from 'react-toastify';
|
|
27
20
|
import { Toast } from '@plone/volto/components';
|
|
28
|
-
|
|
29
21
|
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
30
22
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
31
23
|
|
|
32
|
-
import config from '@plone/volto/registry';
|
|
33
|
-
|
|
34
24
|
const messages = defineMessages({
|
|
35
25
|
login: {
|
|
36
26
|
id: 'Log in',
|
|
@@ -76,59 +66,21 @@ const messages = defineMessages({
|
|
|
76
66
|
},
|
|
77
67
|
});
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}),
|
|
95
|
-
loading: PropTypes.bool,
|
|
96
|
-
token: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
|
|
97
|
-
returnUrl: PropTypes.string,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Default properties.
|
|
102
|
-
* @property {Object} defaultProps Default properties.
|
|
103
|
-
* @static
|
|
104
|
-
*/
|
|
105
|
-
static defaultProps = {
|
|
106
|
-
error: null,
|
|
107
|
-
loading: null,
|
|
108
|
-
token: null,
|
|
109
|
-
returnUrl: null,
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Constructor
|
|
114
|
-
* @method constructor
|
|
115
|
-
* @param {Object} props Component properties
|
|
116
|
-
* @constructs WysiwygEditor
|
|
117
|
-
*/
|
|
118
|
-
constructor(props) {
|
|
119
|
-
super(props);
|
|
120
|
-
this.onLogin = this.onLogin.bind(this);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Component will receive props
|
|
125
|
-
* @method componentWillReceiveProps
|
|
126
|
-
* @param {Object} nextProps Next properties
|
|
127
|
-
* @returns {undefined}
|
|
128
|
-
*/
|
|
129
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
130
|
-
if (nextProps.token) {
|
|
131
|
-
this.props.history.push(this.props.returnUrl || '/');
|
|
69
|
+
const Login = (props) => {
|
|
70
|
+
const intl = useIntl();
|
|
71
|
+
const history = useHistory();
|
|
72
|
+
const location = useLocation();
|
|
73
|
+
const dispatch = useDispatch();
|
|
74
|
+
const token = useSelector((state) => state.userSession.token, shallowEqual);
|
|
75
|
+
const error = useSelector((state) => state.userSession.login.error);
|
|
76
|
+
const loading = useSelector((state) => state.userSession.login.loading);
|
|
77
|
+
const returnUrl =
|
|
78
|
+
qs.parse(props.location.search ?? location.search).return_url ||
|
|
79
|
+
location.pathname.replace(/\/login\/?$/, '').replace(/\/logout\/?$/, '') ||
|
|
80
|
+
'/';
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (token && !props.isLogout) {
|
|
83
|
+
history.push(returnUrl || '/');
|
|
132
84
|
if (toast.isActive('loggedOut')) {
|
|
133
85
|
toast.dismiss('loggedOut');
|
|
134
86
|
}
|
|
@@ -136,7 +88,7 @@ class Login extends Component {
|
|
|
136
88
|
toast.dismiss('loginFailed');
|
|
137
89
|
}
|
|
138
90
|
}
|
|
139
|
-
if (
|
|
91
|
+
if (error) {
|
|
140
92
|
if (toast.isActive('loggedOut')) {
|
|
141
93
|
toast.dismiss('loggedOut');
|
|
142
94
|
}
|
|
@@ -144,189 +96,155 @@ class Login extends Component {
|
|
|
144
96
|
toast.error(
|
|
145
97
|
<Toast
|
|
146
98
|
error
|
|
147
|
-
title={
|
|
148
|
-
content={
|
|
99
|
+
title={intl.formatMessage(messages.loginFailed)}
|
|
100
|
+
content={intl.formatMessage(messages.loginFailedContent)}
|
|
149
101
|
/>,
|
|
150
102
|
{ autoClose: false, toastId: 'loginFailed' },
|
|
151
103
|
);
|
|
152
104
|
}
|
|
153
105
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
}
|
|
106
|
+
return () => {
|
|
107
|
+
if (toast.isActive('loginFailed')) {
|
|
108
|
+
toast.dismiss('loginFailed');
|
|
109
|
+
dispatch(resetLoginRequest());
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}, [dispatch, token, error, intl, history, returnUrl, props.isLogout]);
|
|
161
113
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
onLogin(event) {
|
|
169
|
-
this.props.login(
|
|
170
|
-
document.getElementsByName('login')[0].value,
|
|
171
|
-
document.getElementsByName('password')[0].value,
|
|
114
|
+
const onLogin = (event) => {
|
|
115
|
+
dispatch(
|
|
116
|
+
login(
|
|
117
|
+
document.getElementsByName('login')[0].value,
|
|
118
|
+
document.getElementsByName('password')[0].value,
|
|
119
|
+
),
|
|
172
120
|
);
|
|
173
121
|
event.preventDefault();
|
|
174
|
-
}
|
|
122
|
+
};
|
|
175
123
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
tabIndex={0}
|
|
248
|
-
/>
|
|
249
|
-
</Grid.Column>
|
|
250
|
-
</Grid.Row>
|
|
251
|
-
</Grid>
|
|
252
|
-
</Form.Field>
|
|
253
|
-
<Form.Field inline className="help">
|
|
254
|
-
<Grid>
|
|
255
|
-
<Grid.Row stretched>
|
|
256
|
-
{config.settings.showSelfRegistration && (
|
|
257
|
-
<Grid.Column stretched width="12">
|
|
258
|
-
<p className="help">
|
|
259
|
-
<Link to="/register">
|
|
260
|
-
{this.props.intl.formatMessage(messages.register)}
|
|
261
|
-
</Link>
|
|
262
|
-
</p>
|
|
263
|
-
</Grid.Column>
|
|
264
|
-
)}
|
|
124
|
+
return (
|
|
125
|
+
<div id="page-login">
|
|
126
|
+
<Helmet title={intl.formatMessage(messages.Login)} />
|
|
127
|
+
<Container text>
|
|
128
|
+
<Form method="post" onSubmit={onLogin}>
|
|
129
|
+
<Segment.Group raised>
|
|
130
|
+
<Segment className="primary">
|
|
131
|
+
<FormattedMessage id="Log In" defaultMessage="Login" />
|
|
132
|
+
</Segment>
|
|
133
|
+
<Segment secondary>
|
|
134
|
+
<FormattedMessage
|
|
135
|
+
id="Sign in to start session"
|
|
136
|
+
defaultMessage="Sign in to start session"
|
|
137
|
+
/>
|
|
138
|
+
</Segment>
|
|
139
|
+
<Segment className="form">
|
|
140
|
+
<Form.Field inline className="help">
|
|
141
|
+
<Grid>
|
|
142
|
+
<Grid.Row stretched>
|
|
143
|
+
<Grid.Column width="4">
|
|
144
|
+
<div className="wrapper">
|
|
145
|
+
<label htmlFor="login">
|
|
146
|
+
<FormattedMessage
|
|
147
|
+
id="Login Name"
|
|
148
|
+
defaultMessage="Login Name"
|
|
149
|
+
/>
|
|
150
|
+
</label>
|
|
151
|
+
</div>
|
|
152
|
+
</Grid.Column>
|
|
153
|
+
<Grid.Column width="8">
|
|
154
|
+
{/* eslint-disable jsx-a11y/no-autofocus */}
|
|
155
|
+
<Input
|
|
156
|
+
id="login"
|
|
157
|
+
name="login"
|
|
158
|
+
placeholder={intl.formatMessage(messages.loginName)}
|
|
159
|
+
autoFocus
|
|
160
|
+
/>
|
|
161
|
+
</Grid.Column>
|
|
162
|
+
</Grid.Row>
|
|
163
|
+
</Grid>
|
|
164
|
+
</Form.Field>
|
|
165
|
+
<Form.Field inline className="help">
|
|
166
|
+
<Grid>
|
|
167
|
+
<Grid.Row stretched>
|
|
168
|
+
<Grid.Column stretched width="4">
|
|
169
|
+
<div className="wrapper">
|
|
170
|
+
<label htmlFor="password">
|
|
171
|
+
<FormattedMessage
|
|
172
|
+
id="Password"
|
|
173
|
+
defaultMessage="Password"
|
|
174
|
+
/>
|
|
175
|
+
</label>
|
|
176
|
+
</div>
|
|
177
|
+
</Grid.Column>
|
|
178
|
+
<Grid.Column stretched width="8">
|
|
179
|
+
<Input
|
|
180
|
+
type="password"
|
|
181
|
+
id="password"
|
|
182
|
+
autoComplete="current-password"
|
|
183
|
+
name="password"
|
|
184
|
+
placeholder={intl.formatMessage(messages.password)}
|
|
185
|
+
tabIndex={0}
|
|
186
|
+
/>
|
|
187
|
+
</Grid.Column>
|
|
188
|
+
</Grid.Row>
|
|
189
|
+
</Grid>
|
|
190
|
+
</Form.Field>
|
|
191
|
+
<Form.Field inline className="help">
|
|
192
|
+
<Grid>
|
|
193
|
+
<Grid.Row stretched>
|
|
194
|
+
{config.settings.showSelfRegistration && (
|
|
265
195
|
<Grid.Column stretched width="12">
|
|
266
196
|
<p className="help">
|
|
267
|
-
<Link to="/
|
|
268
|
-
{
|
|
269
|
-
messages.forgotPassword,
|
|
270
|
-
)}
|
|
197
|
+
<Link to="/register">
|
|
198
|
+
{intl.formatMessage(messages.register)}
|
|
271
199
|
</Link>
|
|
272
200
|
</p>
|
|
273
201
|
</Grid.Column>
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
202
|
+
)}
|
|
203
|
+
<Grid.Column stretched width="12">
|
|
204
|
+
<p className="help">
|
|
205
|
+
<Link to="/passwordreset">
|
|
206
|
+
{intl.formatMessage(messages.forgotPassword)}
|
|
207
|
+
</Link>
|
|
208
|
+
</p>
|
|
209
|
+
</Grid.Column>
|
|
210
|
+
</Grid.Row>
|
|
211
|
+
</Grid>
|
|
212
|
+
</Form.Field>
|
|
213
|
+
</Segment>
|
|
214
|
+
<Segment className="actions" clearing>
|
|
215
|
+
<Button
|
|
216
|
+
basic
|
|
217
|
+
primary
|
|
218
|
+
icon
|
|
219
|
+
floated="right"
|
|
220
|
+
type="submit"
|
|
221
|
+
id="login-form-submit"
|
|
222
|
+
aria-label={intl.formatMessage(messages.login)}
|
|
223
|
+
title={intl.formatMessage(messages.login)}
|
|
224
|
+
loading={loading}
|
|
225
|
+
>
|
|
226
|
+
<Icon className="circled" name={aheadSVG} size="30px" />
|
|
227
|
+
</Button>
|
|
292
228
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
229
|
+
<Button
|
|
230
|
+
basic
|
|
231
|
+
secondary
|
|
232
|
+
icon
|
|
233
|
+
floated="right"
|
|
234
|
+
id="login-form-cancel"
|
|
235
|
+
as={Link}
|
|
236
|
+
to="/"
|
|
237
|
+
aria-label={intl.formatMessage(messages.cancel)}
|
|
238
|
+
title={intl.formatMessage(messages.cancel)}
|
|
239
|
+
>
|
|
240
|
+
<Icon className="circled" name={clearSVG} size="30px" />
|
|
241
|
+
</Button>
|
|
242
|
+
</Segment>
|
|
243
|
+
</Segment.Group>
|
|
244
|
+
</Form>
|
|
245
|
+
</Container>
|
|
246
|
+
</div>
|
|
247
|
+
);
|
|
248
|
+
};
|
|
314
249
|
|
|
315
|
-
export default
|
|
316
|
-
withRouter,
|
|
317
|
-
injectIntl,
|
|
318
|
-
connect(
|
|
319
|
-
(state, props) => ({
|
|
320
|
-
error: state.userSession.login.error,
|
|
321
|
-
loading: state.userSession.login.loading,
|
|
322
|
-
token: state.userSession.token,
|
|
323
|
-
returnUrl:
|
|
324
|
-
qs.parse(props.location.search).return_url ||
|
|
325
|
-
props.location.pathname
|
|
326
|
-
.replace(/\/login\/?$/, '')
|
|
327
|
-
.replace(/\/logout\/?$/, '') ||
|
|
328
|
-
'/',
|
|
329
|
-
}),
|
|
330
|
-
{ login },
|
|
331
|
-
),
|
|
332
|
-
)(Login);
|
|
250
|
+
export default Login;
|
|
@@ -14,12 +14,142 @@ beforeAll(() => {
|
|
|
14
14
|
const mockStore = configureStore();
|
|
15
15
|
|
|
16
16
|
describe('Multilingual Logo', () => {
|
|
17
|
-
it('renders a logo component
|
|
17
|
+
it('renders a logo component in a multilingual site root', () => {
|
|
18
18
|
const store = mockStore({
|
|
19
19
|
intl: {
|
|
20
20
|
locale: 'en',
|
|
21
21
|
messages: {},
|
|
22
22
|
},
|
|
23
|
+
navroot: {
|
|
24
|
+
data: {
|
|
25
|
+
id: 'http://localhost:3000/@navroot',
|
|
26
|
+
navroot: {
|
|
27
|
+
'@id': 'http://localhost:3000',
|
|
28
|
+
title: 'Plone Site',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
router: {
|
|
33
|
+
location: {
|
|
34
|
+
pathname: '/',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
site: {
|
|
38
|
+
data: {},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const component = renderer.create(
|
|
42
|
+
<Provider store={store}>
|
|
43
|
+
<MemoryRouter>
|
|
44
|
+
<Logo />
|
|
45
|
+
</MemoryRouter>
|
|
46
|
+
</Provider>,
|
|
47
|
+
);
|
|
48
|
+
const json = component.toJSON();
|
|
49
|
+
expect(json).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('renders a logo component in a multilingual site language root', () => {
|
|
53
|
+
const store = mockStore({
|
|
54
|
+
intl: {
|
|
55
|
+
locale: 'en',
|
|
56
|
+
messages: {},
|
|
57
|
+
},
|
|
58
|
+
navroot: {
|
|
59
|
+
data: {
|
|
60
|
+
id: 'http://localhost:3000/en/@navroot',
|
|
61
|
+
navroot: {
|
|
62
|
+
'@id': 'http://localhost:3000/en',
|
|
63
|
+
title: 'English',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
router: {
|
|
68
|
+
location: {
|
|
69
|
+
pathname: '/en',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
site: {
|
|
73
|
+
data: {
|
|
74
|
+
'plone.site_title': 'Plone Site',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
const component = renderer.create(
|
|
79
|
+
<Provider store={store}>
|
|
80
|
+
<MemoryRouter>
|
|
81
|
+
<Logo />
|
|
82
|
+
</MemoryRouter>
|
|
83
|
+
</Provider>,
|
|
84
|
+
);
|
|
85
|
+
const json = component.toJSON();
|
|
86
|
+
expect(json).toMatchSnapshot();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('renders a logo component with a custom logo in a non-root url', () => {
|
|
90
|
+
const store = mockStore({
|
|
91
|
+
intl: {
|
|
92
|
+
locale: 'en',
|
|
93
|
+
messages: {},
|
|
94
|
+
},
|
|
95
|
+
navroot: {
|
|
96
|
+
data: {
|
|
97
|
+
id: 'http://localhost:3000/en/@navroot',
|
|
98
|
+
navroot: {
|
|
99
|
+
'@id': 'http://localhost:3000/en',
|
|
100
|
+
title: 'English',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
router: {
|
|
105
|
+
location: {
|
|
106
|
+
pathname: '/en',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
site: {
|
|
110
|
+
data: {
|
|
111
|
+
'plone.site_logo':
|
|
112
|
+
'http://localhost:3000/@@site-logo/logo.cab945d8.svg',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
const component = renderer.create(
|
|
117
|
+
<Provider store={store}>
|
|
118
|
+
<MemoryRouter>
|
|
119
|
+
<Logo />
|
|
120
|
+
</MemoryRouter>
|
|
121
|
+
</Provider>,
|
|
122
|
+
);
|
|
123
|
+
const json = component.toJSON();
|
|
124
|
+
expect(json).toMatchSnapshot();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('renders a logo component with a custom logo in a non-root url with path', () => {
|
|
128
|
+
const store = mockStore({
|
|
129
|
+
intl: {
|
|
130
|
+
locale: 'en',
|
|
131
|
+
messages: {},
|
|
132
|
+
},
|
|
133
|
+
navroot: {
|
|
134
|
+
data: {
|
|
135
|
+
id: 'http://localhost:3000/en/@navroot',
|
|
136
|
+
navroot: {
|
|
137
|
+
'@id': 'http://localhost:3000/en',
|
|
138
|
+
title: 'English',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
router: {
|
|
143
|
+
location: {
|
|
144
|
+
pathname: '/en/my/path',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
site: {
|
|
148
|
+
data: {
|
|
149
|
+
'plone.site_logo':
|
|
150
|
+
'http://localhost:3000/@@site-logo/logo.cab945d8.svg',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
23
153
|
});
|
|
24
154
|
const component = renderer.create(
|
|
25
155
|
<Provider store={store}>
|