@plone/volto 18.3.0 → 18.5.0

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 (79) hide show
  1. package/.release-it.json +1 -1
  2. package/CHANGELOG.md +33 -0
  3. package/README.md +32 -8
  4. package/locales/ca/LC_MESSAGES/volto.po +5 -0
  5. package/locales/ca.json +1 -1
  6. package/locales/de/LC_MESSAGES/volto.po +5 -0
  7. package/locales/de.json +1 -1
  8. package/locales/en/LC_MESSAGES/volto.po +5 -0
  9. package/locales/en.json +1 -1
  10. package/locales/es/LC_MESSAGES/volto.po +5 -0
  11. package/locales/es.json +1 -1
  12. package/locales/eu/LC_MESSAGES/volto.po +5 -0
  13. package/locales/eu.json +1 -1
  14. package/locales/fi/LC_MESSAGES/volto.po +5 -0
  15. package/locales/fi.json +1 -1
  16. package/locales/fr/LC_MESSAGES/volto.po +5 -0
  17. package/locales/fr.json +1 -1
  18. package/locales/hi/LC_MESSAGES/volto.po +5 -0
  19. package/locales/hi.json +1 -1
  20. package/locales/it/LC_MESSAGES/volto.po +5 -0
  21. package/locales/it.json +1 -1
  22. package/locales/ja/LC_MESSAGES/volto.po +5 -0
  23. package/locales/ja.json +1 -1
  24. package/locales/nl/LC_MESSAGES/volto.po +5 -0
  25. package/locales/nl.json +1 -1
  26. package/locales/pt/LC_MESSAGES/volto.po +5 -0
  27. package/locales/pt.json +1 -1
  28. package/locales/pt_BR/LC_MESSAGES/volto.po +5 -0
  29. package/locales/pt_BR.json +1 -1
  30. package/locales/ro/LC_MESSAGES/volto.po +5 -0
  31. package/locales/ro.json +1 -1
  32. package/locales/sv/LC_MESSAGES/volto.po +5193 -0
  33. package/locales/sv.json +1 -0
  34. package/locales/volto.pot +5 -0
  35. package/locales/zh_CN/LC_MESSAGES/volto.po +5 -0
  36. package/locales/zh_CN.json +1 -1
  37. package/package.json +4 -4
  38. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +3 -0
  39. package/src/components/manage/Contents/Contents.jsx +6 -0
  40. package/src/components/theme/App/App.jsx +5 -2
  41. package/src/components/theme/RelatedItems/RelatedItems.jsx +70 -0
  42. package/src/components/theme/RelatedItems/RelatedItems.test.jsx +83 -0
  43. package/src/config/index.js +1 -0
  44. package/src/config/slots.js +5 -0
  45. package/src/constants/Languages.cjs +1 -0
  46. package/src/helpers/Html/Html.jsx +6 -0
  47. package/src/helpers/Robots/Robots.js +3 -1
  48. package/test-setup-config.jsx +1 -0
  49. package/theme/themes/pastanaga/extras/main.less +5 -0
  50. package/tsconfig.declarations.json +3 -1
  51. package/types/components/manage/Contents/ContentsDeleteModal.d.ts +10 -0
  52. package/types/components/theme/Navigation/ContextNavigation.d.ts +1 -1
  53. package/types/components/theme/RelatedItems/RelatedItems.d.ts +13 -0
  54. package/types/components/theme/RelatedItems/RelatedItems.test.d.ts +1 -0
  55. package/types/components/theme/View/RenderBlocks.d.ts +1 -1
  56. package/types/components/theme/Widgets/ArrayWidget.d.ts +1 -1
  57. package/types/components/theme/Widgets/DateWidget.d.ts +1 -1
  58. package/types/components/theme/Widgets/DatetimeWidget.d.ts +1 -1
  59. package/types/components/theme/Widgets/DescriptionWidget.d.ts +1 -1
  60. package/types/components/theme/Widgets/EmailWidget.d.ts +1 -1
  61. package/types/components/theme/Widgets/FileWidget.d.ts +1 -1
  62. package/types/components/theme/Widgets/ImageWidget.d.ts +1 -1
  63. package/types/components/theme/Widgets/PasswordWidget.d.ts +1 -1
  64. package/types/components/theme/Widgets/RelationWidget.d.ts +1 -1
  65. package/types/components/theme/Widgets/RelationsWidget.d.ts +1 -1
  66. package/types/components/theme/Widgets/RichTextWidget.d.ts +1 -1
  67. package/types/components/theme/Widgets/SelectWidget.d.ts +1 -1
  68. package/types/components/theme/Widgets/TextWidget.d.ts +1 -1
  69. package/types/components/theme/Widgets/TitleWidget.d.ts +1 -1
  70. package/types/components/theme/Widgets/TokenWidget.d.ts +1 -1
  71. package/types/components/theme/Widgets/UrlWidget.d.ts +1 -1
  72. package/types/config/Blocks.d.ts +1 -0
  73. package/types/config/Views.d.ts +1 -0
  74. package/types/config/Widgets.d.ts +1 -0
  75. package/types/config/slots.d.ts +10 -2
  76. package/types/constants/Languages.d.cts +1 -0
  77. package/types/reducers/index.d.ts +2 -0
  78. package/types/reducers/linkIntegrity/linkIntegrity.d.ts +8 -0
  79. package/types/reducers/linkIntegrity/linkIntegrity.test.d.ts +1 -0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * RelatedItems component.
3
+ * @module components/theme/RelatedItems/RelatedItems
4
+ */
5
+
6
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
7
+ import { defineMessages, useIntl } from 'react-intl';
8
+ import PropTypes from 'prop-types';
9
+ import { Container } from 'semantic-ui-react';
10
+ import config from '@plone/volto/registry';
11
+
12
+ const messages = defineMessages({
13
+ relatedItems: {
14
+ id: 'Related Items',
15
+ defaultMessage: 'Related Items',
16
+ },
17
+ });
18
+
19
+ /**
20
+ * Related Items component.
21
+ * @function RelatedItems
22
+ * @param {array} relatedItems Array of related items.
23
+ * @returns {JSX.Element} Markup of the component.
24
+ */
25
+ const RelatedItems = ({ content }) => {
26
+ const intl = useIntl();
27
+ const relatedItems = content?.relatedItems;
28
+ if (
29
+ !config.settings.showRelatedItems ||
30
+ !relatedItems ||
31
+ relatedItems.length === 0
32
+ ) {
33
+ return null;
34
+ }
35
+
36
+ return (
37
+ <Container className="related-items">
38
+ <h2>{intl.formatMessage(messages.relatedItems)}</h2>
39
+ <ul>
40
+ {relatedItems.map((relatedItem) =>
41
+ relatedItem ? (
42
+ <li key={relatedItem['@id']}>
43
+ <UniversalLink href={relatedItem['@id']}>
44
+ {relatedItem.title}
45
+ </UniversalLink>
46
+ </li>
47
+ ) : null,
48
+ )}
49
+ </ul>
50
+ </Container>
51
+ );
52
+ };
53
+
54
+ /**
55
+ * Property types.
56
+ * @property {Object} propTypes Property types.
57
+ * @static
58
+ */
59
+ RelatedItems.propTypes = {
60
+ content: PropTypes.shape({
61
+ relatedItems: PropTypes.arrayOf(
62
+ PropTypes.shape({
63
+ '@id': PropTypes.string.isRequired,
64
+ title: PropTypes.string.isRequired,
65
+ }),
66
+ ),
67
+ }),
68
+ };
69
+
70
+ export default RelatedItems;
@@ -0,0 +1,83 @@
1
+ import renderer from 'react-test-renderer';
2
+ import configureStore from 'redux-mock-store';
3
+ import { Provider } from 'react-intl-redux';
4
+ import { MemoryRouter } from 'react-router-dom';
5
+
6
+ import RelatedItems from './RelatedItems';
7
+
8
+ const mockStore = configureStore();
9
+ let store;
10
+
11
+ describe('Related Items', () => {
12
+ beforeEach(() => {
13
+ store = mockStore({
14
+ intl: {
15
+ locale: 'en',
16
+ messages: {},
17
+ },
18
+ });
19
+ });
20
+
21
+ it('renders without related items', () => {
22
+ const content = {};
23
+ const component = renderer.create(
24
+ <Provider store={store}>
25
+ <MemoryRouter>
26
+ <RelatedItems content={content} />
27
+ </MemoryRouter>
28
+ </Provider>,
29
+ );
30
+ const json = component.toJSON();
31
+ expect(json).toMatchSnapshot();
32
+ });
33
+
34
+ it('renders with related items', () => {
35
+ const content = {
36
+ relatedItems: [
37
+ {
38
+ '@id': '/test-1',
39
+ title: 'Title 1',
40
+ description: 'Description 1',
41
+ },
42
+ {
43
+ '@id': '/test-2',
44
+ title: 'Title 2',
45
+ description: 'Description 2',
46
+ },
47
+ ],
48
+ };
49
+
50
+ const component = renderer.create(
51
+ <Provider store={store}>
52
+ <MemoryRouter>
53
+ <RelatedItems content={content} />
54
+ </MemoryRouter>
55
+ </Provider>,
56
+ );
57
+ const json = component.toJSON();
58
+ expect(json).toMatchSnapshot();
59
+ });
60
+
61
+ it('renders with related items has null', () => {
62
+ const content = {
63
+ relatedItems: [
64
+ {
65
+ '@id': '/test-1',
66
+ title: 'Title 1',
67
+ description: 'Description 1',
68
+ },
69
+ null,
70
+ ],
71
+ };
72
+
73
+ const component = renderer.create(
74
+ <Provider store={store}>
75
+ <MemoryRouter>
76
+ <RelatedItems content={content} />
77
+ </MemoryRouter>
78
+ </Provider>,
79
+ );
80
+ const json = component.toJSON();
81
+ expect(json).toMatchSnapshot();
82
+ });
83
+ });
@@ -141,6 +141,7 @@ let config = {
141
141
  serverConfig,
142
142
  storeExtenders: [],
143
143
  showTags: true,
144
+ showRelatedItems: false,
144
145
  controlpanels: [],
145
146
  controlPanelsIcons,
146
147
  filterControlPanels,
@@ -1,3 +1,4 @@
1
+ import RelatedItems from '@plone/volto/components/theme/RelatedItems/RelatedItems';
1
2
  import Tags from '@plone/volto/components/theme/Tags/Tags';
2
3
 
3
4
  const slots = {
@@ -6,6 +7,10 @@ const slots = {
6
7
  name: 'tags',
7
8
  component: Tags,
8
9
  },
10
+ {
11
+ name: 'relatedItems',
12
+ component: RelatedItems,
13
+ },
9
14
  ],
10
15
  };
11
16
 
@@ -19,6 +19,7 @@ module.exports = {
19
19
  pt: 'Português',
20
20
  pt_BR: 'Português (Brasil)',
21
21
  zh_CN: '中文',
22
+ sv: 'Svenska',
22
23
  };
23
24
 
24
25
  // export default languages;
@@ -102,6 +102,12 @@ class Html extends Component {
102
102
  {head.meta.toComponent()}
103
103
  {head.link.toComponent()}
104
104
  {head.script.toComponent()}
105
+
106
+ {config.settings.cssLayers && (
107
+ // Load the CSS layers from config, if any
108
+ <style>{`@layer ${config.settings.cssLayers.join(', ')};`}</style>
109
+ )}
110
+
105
111
  {head.style.toComponent()}
106
112
 
107
113
  <script
@@ -16,7 +16,9 @@ import { addHeadersFactory } from '@plone/volto/helpers/Proxy/Proxy';
16
16
  export const generateRobots = (req) =>
17
17
  new Promise((resolve) => {
18
18
  const internalUrl =
19
- config.settings.internalApiPath ?? config.settings.apiPath;
19
+ config.settings.internalApiPath ??
20
+ config.settings.devProxyToApiPath ??
21
+ config.settings.apiPath;
20
22
  const request = superagent.get(`${internalUrl}/robots.txt`);
21
23
  request.set('Accept', 'text/plain');
22
24
  const authToken = req.universalCookies.get('auth_token');
@@ -34,6 +34,7 @@ config.set('settings', {
34
34
  supportedLanguages: ['en'],
35
35
  defaultPageSize: 25,
36
36
  showTags: true,
37
+ showRelatedItems: true,
37
38
  isMultilingual: false,
38
39
  nonContentRoutes,
39
40
  nonContentRoutesPublic,
@@ -651,6 +651,11 @@ img.responsive {
651
651
  height: auto;
652
652
  }
653
653
 
654
+ // Related Items
655
+ .related-items {
656
+ margin-top: 20px;
657
+ }
658
+
654
659
  // Deprecated as per https://github.com/plone/volto/issues/1265
655
660
  // @import 'utils';
656
661
  @import (multiple) '../extras/fonts';
@@ -11,7 +11,9 @@
11
11
  "preserveSymlinks": true,
12
12
  "downlevelIteration": true,
13
13
  "paths": {
14
- "@plone/volto/*": ["./src/*"]
14
+ "@plone/volto/*": ["./src/*"],
15
+ "react": ["./node_modules/@types/react"],
16
+ "react-dom": ["./node_modules/@types/react-dom"]
15
17
  }
16
18
  },
17
19
  "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.tsx"]
@@ -0,0 +1,10 @@
1
+ export default ContentsDeleteModal;
2
+ declare function ContentsDeleteModal(props: any): import("react/jsx-runtime").JSX.Element;
3
+ declare namespace ContentsDeleteModal {
4
+ namespace propTypes {
5
+ let itemsToDelete: any;
6
+ let open: any;
7
+ let onOk: any;
8
+ let onCancel: any;
9
+ }
10
+ }
@@ -3,7 +3,7 @@
3
3
  * portlet. It uses the same API, so the options are similar to
4
4
  * INavigationPortlet
5
5
  */
6
- export function ContextNavigationComponent(props: any): import("react/jsx-runtime").JSX.Element | "";
6
+ export function ContextNavigationComponent(props: any): "" | import("react/jsx-runtime").JSX.Element;
7
7
  export namespace ContextNavigationComponent {
8
8
  namespace propTypes {
9
9
  let navigation: any;
@@ -0,0 +1,13 @@
1
+ export default RelatedItems;
2
+ /**
3
+ * Related Items component.
4
+ * @function RelatedItems
5
+ * @param {array} relatedItems Array of related items.
6
+ * @returns {JSX.Element} Markup of the component.
7
+ */
8
+ declare function RelatedItems({ content }: any[]): JSX.Element;
9
+ declare namespace RelatedItems {
10
+ namespace propTypes {
11
+ let content: any;
12
+ }
13
+ }
@@ -1,2 +1,2 @@
1
1
  export default RenderBlocks;
2
- declare function RenderBlocks(props: any): import("react/jsx-runtime").JSX.Element | "";
2
+ declare function RenderBlocks(props: any): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function ArrayWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -4,4 +4,4 @@ declare function DateWidget({ value, children, className, format }: {
4
4
  children: any;
5
5
  className: any;
6
6
  format?: string;
7
- }): import("react/jsx-runtime").JSX.Element | "";
7
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -4,4 +4,4 @@ declare function DatetimeWidget({ value, children, className, format }: {
4
4
  children: any;
5
5
  className: any;
6
6
  format?: string;
7
- }): import("react/jsx-runtime").JSX.Element | "";
7
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function DescriptionWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function EmailWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function FileWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -2,4 +2,4 @@ export default ImageWidget;
2
2
  declare function ImageWidget({ value, className }: {
3
3
  value: any;
4
4
  className: any;
5
- }): import("react/jsx-runtime").JSX.Element | "";
5
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function PasswordWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function RelationWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function RelationsWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -2,4 +2,4 @@ export default RichTextWidget;
2
2
  declare function RichTextWidget({ value, className }: {
3
3
  value: any;
4
4
  className: any;
5
- }): import("react/jsx-runtime").JSX.Element | "";
5
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function SelectWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function TextWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function TitleWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function TokenWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -3,4 +3,4 @@ declare function UrlWidget({ value, children, className }: {
3
3
  value: any;
4
4
  children: any;
5
5
  className: any;
6
- }): import("react/jsx-runtime").JSX.Element | "";
6
+ }): "" | import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,4 @@
1
+ export function installDefaultBlocks(config: any): void;
1
2
  export const groupBlocksOrder: {
2
3
  id: string;
3
4
  title: string;
@@ -1,3 +1,4 @@
1
+ export function installDefaultViews(config: any): any;
1
2
  export namespace layoutViews {
2
3
  export { DefaultView as document_view };
3
4
  export { SummaryView as summary_view };
@@ -1,3 +1,4 @@
1
+ export function installDefaultWidgets(config: any): void;
1
2
  export namespace widgetMapping {
2
3
  export namespace id {
3
4
  export { TokenWidget as subjects };
@@ -1,6 +1,6 @@
1
1
  export default slots;
2
2
  declare namespace slots {
3
- let belowContent: {
3
+ let belowContent: ({
4
4
  name: string;
5
5
  component: {
6
6
  ({ content }: {
@@ -17,5 +17,13 @@ declare namespace slots {
17
17
  };
18
18
  };
19
19
  };
20
- }[];
20
+ } | {
21
+ name: string;
22
+ component: {
23
+ ({ content }: any[]): JSX.Element;
24
+ propTypes: {
25
+ content: any;
26
+ };
27
+ };
28
+ })[];
21
29
  }
@@ -13,3 +13,4 @@ export let ja: string;
13
13
  export let pt: string;
14
14
  export let pt_BR: string;
15
15
  export let zh_CN: string;
16
+ export let sv: string;
@@ -18,6 +18,7 @@ declare namespace reducers {
18
18
  export { form };
19
19
  export { groups };
20
20
  export { history };
21
+ export { linkIntegrity };
21
22
  export { messages };
22
23
  export { navigation };
23
24
  export { querystring };
@@ -66,6 +67,7 @@ import emailSend from '@plone/volto/reducers/emailSend/emailSend';
66
67
  import form from '@plone/volto/reducers/form/form';
67
68
  import groups from '@plone/volto/reducers/groups/groups';
68
69
  import history from '@plone/volto/reducers/history/history';
70
+ import linkIntegrity from '@plone/volto/reducers/linkIntegrity/linkIntegrity';
69
71
  import messages from '@plone/volto/reducers/messages/messages';
70
72
  import navigation from '@plone/volto/reducers/navigation/navigation';
71
73
  import querystring from '@plone/volto/reducers/querystring/querystring';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * History reducer.
3
+ * @function linkIntegrity
4
+ * @param {Object} state Current state.
5
+ * @param {Object} action Action to be handled.
6
+ * @returns {Object} New state.
7
+ */
8
+ export default function linkIntegrity(state?: any, action?: any): any;