@plone/volto 17.0.0-alpha.17 → 17.0.0-alpha.19

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 (74) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/CHANGELOG.md +57 -0
  3. package/cypress/support/commands.js +17 -0
  4. package/locales/ca/LC_MESSAGES/volto.po +39 -0
  5. package/locales/ca.json +1 -1
  6. package/locales/de/LC_MESSAGES/volto.po +39 -0
  7. package/locales/de.json +1 -1
  8. package/locales/en/LC_MESSAGES/volto.po +39 -0
  9. package/locales/en.json +1 -1
  10. package/locales/es/LC_MESSAGES/volto.po +39 -0
  11. package/locales/es.json +1 -1
  12. package/locales/eu/LC_MESSAGES/volto.po +39 -0
  13. package/locales/eu.json +1 -1
  14. package/locales/fi/LC_MESSAGES/volto.po +39 -0
  15. package/locales/fi.json +1 -1
  16. package/locales/fr/LC_MESSAGES/volto.po +39 -0
  17. package/locales/fr.json +1 -1
  18. package/locales/it/LC_MESSAGES/volto.po +40 -1
  19. package/locales/it.json +1 -1
  20. package/locales/ja/LC_MESSAGES/volto.po +39 -0
  21. package/locales/ja.json +1 -1
  22. package/locales/nl/LC_MESSAGES/volto.po +39 -0
  23. package/locales/nl.json +1 -1
  24. package/locales/pt/LC_MESSAGES/volto.po +39 -0
  25. package/locales/pt.json +1 -1
  26. package/locales/pt_BR/LC_MESSAGES/volto.po +39 -0
  27. package/locales/pt_BR.json +1 -1
  28. package/locales/ro/LC_MESSAGES/volto.po +39 -0
  29. package/locales/ro.json +1 -1
  30. package/locales/volto.pot +39 -0
  31. package/locales/zh_CN/LC_MESSAGES/volto.po +39 -0
  32. package/locales/zh_CN.json +1 -1
  33. package/package.json +2 -2
  34. package/packages/volto-slate/package.json +1 -1
  35. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.jsx +21 -212
  36. package/packages/volto-slate/src/blocks/Table/schema.js +122 -0
  37. package/packages/volto-slate/src/editor/plugins/StyleMenu/utils.js +14 -5
  38. package/packages/volto-slate/src/utils/blocks.js +7 -0
  39. package/packages/volto-slate/src/widgets/RichTextWidget.jsx +15 -8
  40. package/src/components/index.js +1 -0
  41. package/src/components/manage/Blocks/Search/components/Facets.jsx +6 -2
  42. package/src/components/manage/Blocks/Search/components/SearchInput.jsx +9 -2
  43. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +12 -1
  44. package/src/components/manage/Blocks/ToC/Schema.jsx +5 -1
  45. package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +142 -8
  46. package/src/components/manage/LinksToItem/LinksToItem.jsx +209 -0
  47. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +97 -0
  48. package/src/components/manage/Toolbar/More.jsx +15 -0
  49. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +1 -1
  50. package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +52 -99
  51. package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.jsx +14 -13
  52. package/src/components/theme/Comments/CommentEditModal.jsx +63 -115
  53. package/src/components/theme/ContactForm/ContactForm.jsx +108 -192
  54. package/src/components/theme/ContactForm/ContactForm.stories.jsx +1 -1
  55. package/src/components/theme/ContactForm/ContactForm.test.jsx +2 -3
  56. package/src/components/theme/Login/Login.jsx +1 -1
  57. package/src/components/theme/SearchWidget/SearchWidget.jsx +38 -98
  58. package/src/components/theme/View/LinkView.jsx +51 -79
  59. package/src/config/NonContentRoutes.jsx +1 -0
  60. package/src/config/index.js +2 -0
  61. package/src/config/server.js +2 -0
  62. package/src/express-middleware/ok.js +16 -0
  63. package/src/hooks/client/useClient.js +11 -0
  64. package/src/hooks/index.js +1 -0
  65. package/src/routes.js +9 -0
  66. package/theme/themes/pastanaga/extras/main.less +2 -1
  67. package/theme/themes/pastanaga/extras/toc.less +29 -0
  68. package/news/4351.bugfix +0 -1
  69. package/news/4725.bugfix +0 -1
  70. package/news/4932.bugfix +0 -1
  71. package/news/4941.documentation +0 -1
  72. package/news/4951.breaking +0 -1
  73. package/news/4962.feature +0 -1
  74. package/news/4964.bugfix +0 -1
@@ -1,14 +1,7 @@
1
- /**
2
- * Search widget component.
3
- * @module components/theme/SearchWidget/SearchWidget
4
- */
5
-
6
- import React, { Component } from 'react';
7
- import { withRouter } from 'react-router-dom';
1
+ import { useState } from 'react';
2
+ import { useHistory } from 'react-router-dom';
8
3
  import { Form, Input } from 'semantic-ui-react';
9
- import { compose } from 'redux';
10
- import { PropTypes } from 'prop-types';
11
- import { defineMessages, injectIntl } from 'react-intl';
4
+ import { defineMessages, useIntl } from 'react-intl';
12
5
 
13
6
  import { Icon } from '@plone/volto/components';
14
7
  import zoomSVG from '@plone/volto/icons/zoom.svg';
@@ -24,96 +17,43 @@ const messages = defineMessages({
24
17
  },
25
18
  });
26
19
 
27
- /**
28
- * SearchWidget component class.
29
- * @class SearchWidget
30
- * @extends Component
31
- */
32
- class SearchWidget extends Component {
33
- /**
34
- * Property types.
35
- * @property {Object} propTypes Property types.
36
- * @static
37
- */
38
- static propTypes = {
39
- pathname: PropTypes.string,
20
+ const SearchWidget = (props) => {
21
+ const intl = useIntl();
22
+ const [text, setText] = useState('');
23
+ const history = useHistory();
24
+ const onChangeText = (event, { value }) => {
25
+ setText(value);
40
26
  };
41
-
42
- /**
43
- * Constructor
44
- * @method constructor
45
- * @param {Object} props Component properties
46
- * @constructs WysiwygEditor
47
- */
48
- constructor(props) {
49
- super(props);
50
- this.onChangeText = this.onChangeText.bind(this);
51
- this.onSubmit = this.onSubmit.bind(this);
52
- this.state = {
53
- text: '',
54
- };
55
- }
56
-
57
- /**
58
- * On change text
59
- * @method onChangeText
60
- * @param {object} event Event object.
61
- * @param {string} value Text value.
62
- * @returns {undefined}
63
- */
64
- onChangeText(event, { value }) {
65
- this.setState({
66
- text: value,
67
- });
68
- }
69
-
70
- /**
71
- * Submit handler
72
- * @method onSubmit
73
- * @param {event} event Event object.
74
- * @returns {undefined}
75
- */
76
- onSubmit(event) {
27
+ const pathname = props.pathname;
28
+ const onSubmit = (event) => {
77
29
  const path =
78
- this.props.pathname?.length > 0
79
- ? `&path=${encodeURIComponent(this.props.pathname)}`
80
- : '';
81
- this.props.history.push(
82
- `/search?SearchableText=${encodeURIComponent(this.state.text)}${path}`,
83
- );
30
+ pathname?.length > 0 ? `&path=${encodeURIComponent(pathname)}` : '';
31
+
32
+ history.push(`/search?SearchableText=${encodeURIComponent(text)}${path}`);
84
33
  // reset input value
85
- this.setState({
86
- text: '',
87
- });
34
+ setText('');
88
35
  event.preventDefault();
89
- }
90
-
91
- /**
92
- * Render method.
93
- * @method render
94
- * @returns {string} Markup for the component.
95
- */
96
- render() {
97
- return (
98
- <Form action="/search" onSubmit={this.onSubmit}>
99
- <Form.Field className="searchbox">
100
- <Input
101
- aria-label={this.props.intl.formatMessage(messages.search)}
102
- onChange={this.onChangeText}
103
- name="SearchableText"
104
- value={this.state.text}
105
- transparent
106
- autoComplete="off"
107
- placeholder={this.props.intl.formatMessage(messages.searchSite)}
108
- title={this.props.intl.formatMessage(messages.search)}
109
- />
110
- <button aria-label={this.props.intl.formatMessage(messages.search)}>
111
- <Icon name={zoomSVG} size="18px" />
112
- </button>
113
- </Form.Field>
114
- </Form>
115
- );
116
- }
117
- }
36
+ };
118
37
 
119
- export default compose(withRouter, injectIntl)(SearchWidget);
38
+ return (
39
+ <Form action="/search" onSubmit={onSubmit}>
40
+ <Form.Field className="searchbox">
41
+ <Input
42
+ aria-label={intl.formatMessage(messages.search)}
43
+ onChange={onChangeText}
44
+ name="SearchableText"
45
+ value={text}
46
+ transparent
47
+ autoComplete="off"
48
+ placeholder={intl.formatMessage(messages.searchSite)}
49
+ title={intl.formatMessage(messages.search)}
50
+ />
51
+ <button aria-label={intl.formatMessage(messages.search)}>
52
+ <Icon name={zoomSVG} size="18px" />
53
+ </button>
54
+ </Form.Field>
55
+ </Form>
56
+ );
57
+ };
58
+
59
+ export default SearchWidget;
@@ -1,95 +1,67 @@
1
- /**
2
- * Link View.
3
- * @module components/theme/View/LinkView
4
- */
5
-
6
- import React, { Component } from 'react';
1
+ import { useEffect } from 'react';
7
2
  import PropTypes from 'prop-types';
3
+ import { useHistory } from 'react-router-dom';
8
4
  import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers';
9
5
  import { Container as SemanticContainer } from 'semantic-ui-react';
10
6
  import { UniversalLink } from '@plone/volto/components';
11
7
  import { FormattedMessage } from 'react-intl';
12
8
  import config from '@plone/volto/registry';
13
9
 
14
- /**
15
- * View container class.
16
- * @class View
17
- * @extends Component
18
- */
19
- class LinkView extends Component {
20
- /**
21
- * Property types.
22
- * @property {Object} propTypes Property types.
23
- * @static
24
- */
25
- static propTypes = {
26
- content: PropTypes.shape({
27
- title: PropTypes.string,
28
- description: PropTypes.string,
29
- remoteUrl: PropTypes.string,
30
- }),
31
- token: PropTypes.string,
32
- };
33
-
34
- /**
35
- * Default properties.
36
- * @property {Object} defaultProps Default properties.
37
- * @static
38
- */
39
- static defaultProps = {
40
- content: null,
41
- token: null,
42
- };
43
-
44
- componentDidMount() {
45
- if (!this.props.token) {
46
- const { remoteUrl } = this.props.content;
10
+ const LinkView = ({ token, content }) => {
11
+ const history = useHistory();
12
+ useEffect(() => {
13
+ if (!token) {
14
+ const { remoteUrl } = content;
47
15
  if (isInternalURL(remoteUrl)) {
48
- this.props.history.replace(flattenToAppURL(remoteUrl));
16
+ history.replace(flattenToAppURL(remoteUrl));
49
17
  } else if (!__SERVER__) {
50
18
  window.location.href = flattenToAppURL(remoteUrl);
51
19
  }
52
20
  }
53
- }
21
+ }, [content, history, token]);
22
+ const { title, description, remoteUrl } = content;
23
+ const { openExternalLinkInNewTab } = config.settings;
24
+ const Container =
25
+ config.getComponent({ name: 'Container' }).component || SemanticContainer;
26
+
27
+ return (
28
+ <Container id="page-document">
29
+ <h1 className="documentFirstHeading">{title}</h1>
30
+ {content.description && (
31
+ <p className="documentDescription">{description}</p>
32
+ )}
33
+ {remoteUrl && (
34
+ <p>
35
+ <FormattedMessage
36
+ id="The link address is:"
37
+ defaultMessage="The link address is:"
38
+ />{' '}
39
+ <UniversalLink
40
+ href={remoteUrl}
41
+ openLinkInNewTab={
42
+ openExternalLinkInNewTab && !isInternalURL(remoteUrl)
43
+ }
44
+ >
45
+ {flattenToAppURL(remoteUrl)}
46
+ </UniversalLink>
47
+ </p>
48
+ )}
49
+ </Container>
50
+ );
51
+ };
54
52
 
55
- /**
56
- * Render method.
57
- * @method render
58
- * @returns {string} Markup for the component.
59
- */
60
- render() {
61
- const { remoteUrl } = this.props.content;
62
- const { openExternalLinkInNewTab } = config.settings;
63
- const Container =
64
- config.getComponent({ name: 'Container' }).component || SemanticContainer;
53
+ LinkView.propTypes = {
54
+ content: PropTypes.shape({
55
+ title: PropTypes.string,
56
+ description: PropTypes.string,
57
+ remoteUrl: PropTypes.string,
58
+ }),
59
+ token: PropTypes.string,
60
+ };
65
61
 
66
- return (
67
- <Container id="page-document">
68
- <h1 className="documentFirstHeading">{this.props.content.title}</h1>
69
- {this.props.content.description && (
70
- <p className="documentDescription">
71
- {this.props.content.description}
72
- </p>
73
- )}
74
- {remoteUrl && (
75
- <p>
76
- <FormattedMessage
77
- id="The link address is:"
78
- defaultMessage="The link address is:"
79
- />{' '}
80
- <UniversalLink
81
- href={remoteUrl}
82
- openLinkInNewTab={
83
- openExternalLinkInNewTab && !isInternalURL(remoteUrl)
84
- }
85
- >
86
- {flattenToAppURL(remoteUrl)}
87
- </UniversalLink>
88
- </p>
89
- )}
90
- </Container>
91
- );
92
- }
93
- }
62
+ LinkView.defaultProps = {
63
+ content: null,
64
+ token: null,
65
+ };
94
66
 
95
67
  export default LinkView;
@@ -12,6 +12,7 @@ export const nonContentRoutes = [
12
12
  '/diff',
13
13
  /\/edit$/,
14
14
  '/historyview',
15
+ '/links-to-item',
15
16
  '/layout',
16
17
  '/login',
17
18
  '/logout',
@@ -74,6 +74,7 @@ let config = {
74
74
  port,
75
75
  // The URL Volto is going to be served (see sensible defaults above)
76
76
  publicURL,
77
+ okRoute: '/ok',
77
78
  apiPath,
78
79
  apiExpanders: [
79
80
  // Add the following expanders for only issuing a single request.
@@ -183,6 +184,7 @@ let config = {
183
184
  styleClassNameExtenders,
184
185
  querystringSearchGet: false,
185
186
  blockSettingsTabFieldsetsInitialStateOpen: true,
187
+ excludeLinksAndReferencesMenuItem: false,
186
188
  },
187
189
  experimental: {
188
190
  addBlockButton: {
@@ -1,6 +1,7 @@
1
1
  import imagesMiddleware from '@plone/volto/express-middleware/images';
2
2
  import filesMiddleware from '@plone/volto/express-middleware/files';
3
3
  import robotstxtMiddleware from '@plone/volto/express-middleware/robotstxt';
4
+ import okMiddleware from '@plone/volto/express-middleware/ok';
4
5
  import sitemapMiddleware from '@plone/volto/express-middleware/sitemap';
5
6
  import staticsMiddleware from '@plone/volto/express-middleware/static';
6
7
  import devProxyMiddleware from '@plone/volto/express-middleware/devproxy';
@@ -11,6 +12,7 @@ const settings = {
11
12
  filesMiddleware(),
12
13
  imagesMiddleware(),
13
14
  robotstxtMiddleware(),
15
+ okMiddleware(),
14
16
  sitemapMiddleware(),
15
17
  staticsMiddleware(),
16
18
  ],
@@ -0,0 +1,16 @@
1
+ import express from 'express';
2
+ import config from '@plone/volto/registry';
3
+
4
+ const ok = function (req, res, next) {
5
+ res.type('text/plain');
6
+ res.set('Expires', 'Sat, 1 Jan 2000 00:00:00 GMT');
7
+ res.set('Cache-Control', 'max-age=0, must-revalidate, private');
8
+ res.send('ok');
9
+ };
10
+
11
+ export default function () {
12
+ const middleware = express.Router();
13
+ middleware.all(config?.settings?.okRoute || '/ok', ok);
14
+ middleware.id = 'ok';
15
+ return middleware;
16
+ }
@@ -0,0 +1,11 @@
1
+ //useClient hook to replace repetitive delcaration in the components
2
+ import { useEffect, useState } from 'react';
3
+
4
+ export function useClient() {
5
+ const [isClient, setisClient] = useState(false);
6
+ useEffect(() => {
7
+ setisClient(true);
8
+ }, []);
9
+
10
+ return isClient;
11
+ }
@@ -1 +1,2 @@
1
1
  export useClipboard from '@plone/volto/hooks/clipboard/useClipboard';
2
+ export { useClient } from '@plone/volto/hooks/client/useClient';
package/src/routes.js CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  Diff,
24
24
  Edit,
25
25
  History,
26
+ LinksToItem,
26
27
  Login,
27
28
  Logout,
28
29
  ManageTranslations,
@@ -285,6 +286,14 @@ export const defaultRoutes = [
285
286
  path: '/**/manage-translations',
286
287
  component: ManageTranslations,
287
288
  },
289
+ {
290
+ path: '/links-to-item',
291
+ component: LinksToItem,
292
+ },
293
+ {
294
+ path: '/**/links-to-item',
295
+ component: LinksToItem,
296
+ },
288
297
  {
289
298
  path: '/register',
290
299
  component: Register,
@@ -25,7 +25,7 @@ body {
25
25
  &.has-toolbar-menu-open,
26
26
  &.has-mobile-menu-open {
27
27
  // The body scroll locker when the toolbar or the mobile menu are active in mobile.
28
- @media only screen and (max-width: @largestMobileScreen) {
28
+ @media only screen and (max-width: @largestTabletScreen) {
29
29
  overflow: hidden;
30
30
  }
31
31
  }
@@ -667,5 +667,6 @@ body.has-toolbar-collapsed .mobile-menu {
667
667
  @import 'login';
668
668
  @import 'language-selector';
669
669
  @import 'views';
670
+ @import 'toc';
670
671
  @import 'grid.less';
671
672
  .loadUIOverrides();
@@ -0,0 +1,29 @@
1
+ .table-of-contents.horizontalMenu.sticky-toc {
2
+ position: sticky;
3
+ z-index: 1;
4
+ top: 0;
5
+ }
6
+
7
+ .table-of-contents.horizontalMenu .hidden {
8
+ z-index: -1;
9
+ pointer-events: none;
10
+ visibility: hidden;
11
+ }
12
+
13
+ .table-of-contents.horizontalMenu .hidden-dropdown {
14
+ display: none !important;
15
+ }
16
+
17
+ .table-of-contents.horizontalMenu .item.dropdown {
18
+ position: absolute !important;
19
+ right: 0;
20
+ }
21
+
22
+ .table-of-contents.horizontalMenu > .ui.menu {
23
+ position: relative;
24
+ }
25
+
26
+ .table-of-contents.horizontalMenu .item.dropdown .focused > a {
27
+ border: 2px solid black !important;
28
+ border-radius: 4px;
29
+ }
package/news/4351.bugfix DELETED
@@ -1 +0,0 @@
1
- Fix temporary rendering of folder contents while query results are loading. @davisagli
package/news/4725.bugfix DELETED
@@ -1 +0,0 @@
1
- Fix isBlacklisted method check for volto externalRoutes
package/news/4932.bugfix DELETED
@@ -1 +0,0 @@
1
- Add a marker in the props passed to `RenderBlocks` in the Grid block view @sneridagh
@@ -1 +0,0 @@
1
- Replace broken link for @albertcasado to use GitHub instead of Twitter. @stevepiercy
@@ -1 +0,0 @@
1
- Remove useToken & useContent hooks-@Tishasoumya-02
package/news/4962.feature DELETED
@@ -1 +0,0 @@
1
- Use container from component registry in content type views, if defined. @sneridagh
package/news/4964.bugfix DELETED
@@ -1 +0,0 @@
1
- Fix handling of overriden image in Teaser, improve in case that a custom image component is present. @sneridagh