@plone/volto 18.0.0-alpha.42 → 18.0.0-alpha.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/finalreleasechangelog.py +48 -0
  3. package/locales/ca/LC_MESSAGES/volto.po +8 -12
  4. package/locales/ca.json +1 -1
  5. package/locales/de/LC_MESSAGES/volto.po +9 -13
  6. package/locales/de.json +1 -1
  7. package/locales/en/LC_MESSAGES/volto.po +8 -12
  8. package/locales/en.json +1 -1
  9. package/locales/es/LC_MESSAGES/volto.po +9 -13
  10. package/locales/es.json +1 -1
  11. package/locales/eu/LC_MESSAGES/volto.po +9 -13
  12. package/locales/eu.json +1 -1
  13. package/locales/fi/LC_MESSAGES/volto.po +9 -13
  14. package/locales/fi.json +1 -1
  15. package/locales/fr/LC_MESSAGES/volto.po +9 -13
  16. package/locales/fr.json +1 -1
  17. package/locales/hi/LC_MESSAGES/volto.po +9 -13
  18. package/locales/hi.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +9 -13
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +8 -12
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +8 -12
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +8 -12
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +9 -13
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +8 -12
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +9 -13
  32. package/locales/zh_CN/LC_MESSAGES/volto.po +9 -13
  33. package/locales/zh_CN.json +1 -1
  34. package/package.json +3 -3
  35. package/razzle.config.js +1 -1
  36. package/src/components/manage/Actions/Actions.stories.jsx +138 -0
  37. package/src/components/manage/Add/Add.jsx +7 -4
  38. package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
  39. package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
  40. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
  41. package/src/components/manage/Blocks/Block/Order/Item.jsx +3 -1
  42. package/src/components/manage/Blocks/Grid/View.jsx +3 -0
  43. package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
  44. package/src/components/manage/Blocks/Search/components/SortOn.jsx +82 -55
  45. package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
  46. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
  47. package/src/components/manage/Blocks/ToC/Edit.jsx +36 -29
  48. package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
  49. package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
  50. package/src/components/manage/Contents/Contents.jsx +3 -0
  51. package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
  52. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
  53. package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
  54. package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
  55. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
  56. package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
  57. package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
  58. package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
  59. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
  60. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
  61. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
  62. package/src/components/manage/Display/Display.jsx +92 -148
  63. package/src/components/manage/Display/Display.stories.jsx +46 -0
  64. package/src/components/manage/Edit/Edit.jsx +2 -4
  65. package/src/components/manage/Preferences/ChangePassword.jsx +94 -172
  66. package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
  67. package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
  68. package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
  69. package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
  70. package/src/components/manage/Toolbar/More.jsx +308 -399
  71. package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
  72. package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
  73. package/src/components/theme/Register/Register.jsx +70 -142
  74. package/src/components/theme/Register/Register.stories.jsx +49 -0
  75. package/src/components/theme/Tags/Tags.jsx +19 -10
  76. package/src/components/theme/Tags/Tags.test.jsx +9 -11
  77. package/src/components/theme/View/AlbumView.jsx +122 -167
  78. package/src/components/theme/View/LinkView.jsx +4 -0
  79. package/src/components/theme/View/LinkView.test.jsx +2 -0
  80. package/src/components/theme/View/View.jsx +0 -6
  81. package/src/config/ControlPanels.js +49 -43
  82. package/src/config/config.test.js +1 -0
  83. package/src/config/index.js +16 -0
  84. package/src/config/slots.js +12 -0
  85. package/src/helpers/Blocks/Blocks.js +12 -7
  86. package/src/helpers/Blocks/Blocks.test.js +15 -0
  87. package/src/helpers/Blocks/cloneBlocks.ts +1 -1
  88. package/src/helpers/FormValidation/FormValidation.jsx +19 -2
  89. package/src/helpers/FormValidation/validators.ts +1 -1
  90. package/src/helpers/Url/Url.test.js +15 -2
  91. package/src/helpers/Url/urlRegex.js +1 -1
  92. package/src/helpers/index.js +2 -0
  93. package/src/middleware/api.js +4 -2
  94. package/src/middleware/index.js +1 -0
  95. package/src/middleware/userSessionReset.js +46 -0
  96. package/src/store.js +2 -0
  97. package/test-setup-config.jsx +3 -0
  98. package/theme/themes/pastanaga/extras/blocks.less +6 -0
  99. package/types/components/manage/Actions/Actions.stories.d.ts +8 -0
  100. package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
  101. package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
  102. package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
  103. package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
  104. package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
  105. package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
  106. package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
  107. package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
  108. package/types/components/manage/Contents/index.d.ts +1 -1
  109. package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
  110. package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
  111. package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
  112. package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
  113. package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
  114. package/types/components/manage/Controlpanels/index.d.ts +4 -4
  115. package/types/components/manage/Display/Display.stories.d.ts +8 -0
  116. package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
  117. package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
  118. package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
  119. package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
  120. package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
  121. package/types/components/manage/Toolbar/More.d.ts +8 -5
  122. package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
  123. package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
  124. package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
  125. package/types/components/manage/Widgets/index.d.ts +1 -1
  126. package/types/components/theme/Register/Register.d.ts +2 -2
  127. package/types/components/theme/Register/Register.stories.d.ts +9 -0
  128. package/types/components/theme/Tags/Tags.d.ts +15 -7
  129. package/types/components/theme/View/AlbumView.d.ts +3 -17
  130. package/types/config/ControlPanels.d.ts +8 -0
  131. package/types/config/Widgets.d.ts +1 -1
  132. package/types/config/slots.d.ts +21 -0
  133. package/types/helpers/Blocks/Blocks.d.ts +6 -0
  134. package/types/helpers/FormValidation/FormValidation.d.ts +1 -0
  135. package/types/helpers/index.d.ts +2 -2
  136. package/types/middleware/index.d.ts +1 -0
  137. package/types/middleware/userSessionReset.d.ts +5 -0
@@ -3,19 +3,25 @@
3
3
  * @module components/theme/Tags/Tags
4
4
  */
5
5
 
6
- import React from 'react';
7
6
  import { Link } from 'react-router-dom';
8
7
  import PropTypes from 'prop-types';
9
8
  import { Container } from 'semantic-ui-react';
9
+ import config from '@plone/registry';
10
10
 
11
11
  /**
12
- * Tags component class.
12
+ * Tags component.
13
13
  * @function Tags
14
- * @param {array} tags Array of tags.
15
- * @returns {string} Markup of the component.
14
+ * @param {Object} props Component properties.
15
+ * @param {Object} props.content Content object that may contain subjects.
16
+ * @param {Array} [props.content.subjects] Optional array of tags (subjects).
17
+ * @returns {JSX.Element|null} Markup of the component or null if no tags are available.
16
18
  */
17
- const Tags = ({ tags }) =>
18
- tags && tags.length > 0 ? (
19
+ const Tags = ({ content }) => {
20
+ const tags = content?.subjects || [];
21
+
22
+ if (!config.settings.showTags || !tags.length) return null;
23
+
24
+ return (
19
25
  <Container className="tags">
20
26
  {tags.map((tag) => (
21
27
  <Link className="ui label" to={`/search?Subject=${tag}`} key={tag}>
@@ -23,9 +29,8 @@ const Tags = ({ tags }) =>
23
29
  </Link>
24
30
  ))}
25
31
  </Container>
26
- ) : (
27
- <span />
28
32
  );
33
+ };
29
34
 
30
35
  /**
31
36
  * Property types.
@@ -33,7 +38,9 @@ const Tags = ({ tags }) =>
33
38
  * @static
34
39
  */
35
40
  Tags.propTypes = {
36
- tags: PropTypes.arrayOf(PropTypes.string),
41
+ content: PropTypes.shape({
42
+ subjects: PropTypes.arrayOf(PropTypes.string),
43
+ }),
37
44
  };
38
45
 
39
46
  /**
@@ -42,7 +49,9 @@ Tags.propTypes = {
42
49
  * @static
43
50
  */
44
51
  Tags.defaultProps = {
45
- tags: null,
52
+ content: {
53
+ subjects: [],
54
+ },
46
55
  };
47
56
 
48
57
  export default Tags;
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import renderer from 'react-test-renderer';
3
2
  import configureStore from 'redux-mock-store';
4
3
  import { Provider } from 'react-intl-redux';
@@ -9,17 +8,22 @@ import Tags from './Tags';
9
8
  const mockStore = configureStore();
10
9
 
11
10
  describe('Tags', () => {
12
- it('renders without tags', () => {
13
- const store = mockStore({
11
+ let store;
12
+
13
+ beforeEach(() => {
14
+ store = mockStore({
14
15
  intl: {
15
16
  locale: 'en',
16
17
  messages: {},
17
18
  },
18
19
  });
20
+ });
21
+
22
+ it('renders without tags', () => {
19
23
  const component = renderer.create(
20
24
  <Provider store={store}>
21
25
  <MemoryRouter>
22
- <Tags />
26
+ <Tags content={{ subjects: [] }} />
23
27
  </MemoryRouter>
24
28
  </Provider>,
25
29
  );
@@ -28,16 +32,10 @@ describe('Tags', () => {
28
32
  });
29
33
 
30
34
  it('renders with tags', () => {
31
- const store = mockStore({
32
- intl: {
33
- locale: 'en',
34
- messages: {},
35
- },
36
- });
37
35
  const component = renderer.create(
38
36
  <Provider store={store}>
39
37
  <MemoryRouter>
40
- <Tags tags={['Tag 1', 'Tag 2']} />
38
+ <Tags content={{ subjects: ['Tag 1', 'Tag 2'] }} />
41
39
  </MemoryRouter>
42
40
  </Provider>,
43
41
  );
@@ -1,9 +1,4 @@
1
- /**
2
- * Album view component.
3
- * @module components/theme/View/AlbumView
4
- */
5
-
6
- import React from 'react';
1
+ import { Fragment, useState } from 'react';
7
2
  import PropTypes from 'prop-types';
8
3
  import {
9
4
  Container as SemanticContainer,
@@ -18,178 +13,138 @@ import openSVG from '@plone/volto/icons/open.svg';
18
13
  import aheadSVG from '@plone/volto/icons/ahead.svg';
19
14
  import backSVG from '@plone/volto/icons/back.svg';
20
15
 
21
- /**
22
- * Album view component class.
23
- * @function AlbumView
24
- * @param {Object} content Content object.
25
- * @returns {string} Markup of the component.
26
- */
27
- class AlbumView extends React.Component {
28
- constructor(props) {
29
- super(props);
30
-
31
- this.state = {
32
- openIndex: undefined,
33
- };
34
-
35
- this.closeModal = this.closeModal.bind(this);
36
- this.nextImage = this.nextImage.bind(this);
37
- this.prevImage = this.prevImage.bind(this);
38
- }
39
-
40
- closeModal() {
41
- this.setState({
42
- openIndex: -1,
43
- });
44
- }
45
-
46
- nextImage() {
47
- const openIndex =
48
- (this.state.openIndex + 1) % this.props.content.items.length;
49
- this.setState({
50
- openIndex,
51
- });
52
- }
53
-
54
- prevImage() {
55
- const openIndex =
56
- (this.state.openIndex - 1) % this.props.content.items.length;
57
- this.setState({
58
- openIndex,
59
- });
60
- }
16
+ const AlbumView = ({ content }) => {
17
+ const [openIndex, setOpenIndex] = useState(undefined);
61
18
 
62
- render() {
63
- const { content } = this.props;
64
- const Container =
65
- config.getComponent({ name: 'Container' }).component || SemanticContainer;
66
- const PreviewImage = config.getComponent({
67
- name: 'PreviewImage',
68
- }).component;
19
+ const closeModal = () => {
20
+ setOpenIndex(-1);
21
+ };
69
22
 
70
- return (
71
- <Container className="view-wrapper">
72
- <article id="content">
73
- <header>
74
- <h1 className="documentFirstHeading">{content.title}</h1>
75
- {content.description && (
76
- <p className="documentDescription">{content.description}</p>
77
- )}
78
- </header>
79
- <section id="content-core">
80
- <Grid doubling stackable columns={4}>
81
- {content.items &&
82
- content.items.map((item, index) => (
83
- <React.Fragment key={item.url}>
84
- {item.image_field && (
85
- <Modal
86
- className="gallery"
87
- onClose={this.closeModal}
88
- open={this.state.openIndex === index}
89
- trigger={
90
- <Grid.Column>
91
- <Segment className="imageborder">
23
+ const nextImage = () => {
24
+ let OpenIndex = (openIndex + 1) % content.items.length;
25
+ setOpenIndex(OpenIndex);
26
+ };
27
+ const prevImage = () => {
28
+ const OpenIndex = (openIndex - 1) % content.items.length;
29
+ setOpenIndex(OpenIndex);
30
+ };
31
+ const Container =
32
+ config.getComponent({ name: 'Container' }).component || SemanticContainer;
33
+ const PreviewImage = config.getComponent({ name: 'PreviewImage' }).component;
34
+ return (
35
+ <Container className="view-wrapper">
36
+ <article id="content">
37
+ <header>
38
+ <h1 className="documentFirstHeading">{content.title}</h1>
39
+ {content.description && (
40
+ <p className="documentDescription">{content.description}</p>
41
+ )}
42
+ </header>
43
+ <section id="content-core">
44
+ <Grid doubling stackable columns={4}>
45
+ {content.items &&
46
+ content.items.map((item, index) => (
47
+ <Fragment key={item.url}>
48
+ {item.image_field && (
49
+ <Modal
50
+ className="gallery"
51
+ onClose={closeModal}
52
+ open={openIndex === index}
53
+ trigger={
54
+ <Grid.Column>
55
+ <Segment className="imageborder">
56
+ <PreviewImage
57
+ item={item}
58
+ alt={item.image_caption || item.title}
59
+ onClick={() => {
60
+ setOpenIndex(index);
61
+ }}
62
+ className="ui middle aligned image"
63
+ responsive={true}
64
+ loading="lazy"
65
+ title={item.title}
66
+ />
67
+ </Segment>
68
+ </Grid.Column>
69
+ }
70
+ closeIcon
71
+ >
72
+ <Modal.Header>
73
+ <Grid>
74
+ <Grid.Row>
75
+ <GridColumn width={10}>{item.title}</GridColumn>
76
+ <GridColumn width={2} textAlign="right">
77
+ <UniversalLink
78
+ href={item.url}
79
+ title={item['@type']}
80
+ onClick={closeModal}
81
+ >
82
+ <Icon size="30px" fitted name={openSVG} />
83
+ </UniversalLink>
84
+ </GridColumn>
85
+ </Grid.Row>
86
+ </Grid>
87
+ </Modal.Header>
88
+ <Grid centered verticalAlign="middle">
89
+ <Grid.Row>
90
+ <Grid.Column width={2} textAlign="center">
91
+ <Button
92
+ className="gallery noborder"
93
+ onClick={prevImage}
94
+ style={{ margin: 0 }}
95
+ >
96
+ <Icon
97
+ name={backSVG}
98
+ className="circled"
99
+ size="30px"
100
+ style={{ margin: 0 }}
101
+ />
102
+ </Button>
103
+ </Grid.Column>
104
+ <Grid.Column width={8}>
105
+ <Modal.Content image>
92
106
  <PreviewImage
93
107
  item={item}
94
- alt={item.image_caption || item.title}
108
+ alt={item.image_caption}
95
109
  onClick={() => {
96
- this.setState({
97
- openIndex: index,
98
- });
110
+ setOpenIndex(index);
99
111
  }}
100
- className="ui middle aligned image"
112
+ className="ui image"
101
113
  responsive={true}
102
- loading="lazy"
103
- title={item.title}
104
114
  />
105
- </Segment>
115
+
116
+ <Modal.Description>
117
+ <p>{item.description}</p>
118
+ </Modal.Description>
119
+ </Modal.Content>
106
120
  </Grid.Column>
107
- }
108
- closeIcon
109
- >
110
- <Modal.Header>
111
- <Grid>
112
- <Grid.Row>
113
- <GridColumn width={10}>{item.title}</GridColumn>
114
- <GridColumn width={2} textAlign="right">
115
- <UniversalLink
116
- href={item.url}
117
- title={item['@type']}
118
- onClick={this.closeModal}
119
- >
120
- <Icon size="30px" fitted name={openSVG} />
121
- </UniversalLink>
122
- </GridColumn>
123
- </Grid.Row>
124
- </Grid>
125
- </Modal.Header>
126
- <Grid centered verticalAlign="middle">
127
- <Grid.Row>
128
- <Grid.Column width={2} textAlign="center">
129
- <Button
130
- className="gallery noborder"
131
- onClick={this.nextImage}
121
+ <Grid.Column width={2} textAlign="center">
122
+ <Button
123
+ onClick={nextImage}
124
+ className="gallery noborder"
125
+ style={{ margin: 0 }}
126
+ >
127
+ <Icon
128
+ name={aheadSVG}
129
+ className="circled"
130
+ size="30px"
132
131
  style={{ margin: 0 }}
133
- >
134
- <Icon
135
- name={backSVG}
136
- className="circled"
137
- size="30px"
138
- style={{ margin: 0 }}
139
- />
140
- </Button>
141
- </Grid.Column>
142
- <Grid.Column width={8}>
143
- <Modal.Content image>
144
- <PreviewImage
145
- item={item}
146
- alt={item.image_caption}
147
- onClick={() => {
148
- this.setState({
149
- openIndex: index,
150
- });
151
- }}
152
- className="ui image"
153
- responsive={true}
154
- />
155
- <Modal.Description>
156
- <p>{item.description}</p>
157
- </Modal.Description>
158
- </Modal.Content>
159
- </Grid.Column>
160
- <Grid.Column width={2} textAlign="center">
161
- <Button
162
- onClick={this.nextImage}
163
- className="gallery noborder"
164
- style={{ margin: 0 }}
165
- >
166
- <Icon
167
- name={aheadSVG}
168
- className="circled"
169
- size="30px"
170
- style={{ margin: 0 }}
171
- />
172
- </Button>
173
- </Grid.Column>
174
- </Grid.Row>
175
- </Grid>
176
- </Modal>
177
- )}
178
- </React.Fragment>
179
- ))}
180
- </Grid>
181
- </section>
182
- </article>
183
- </Container>
184
- );
185
- }
186
- }
132
+ />
133
+ </Button>
134
+ </Grid.Column>
135
+ </Grid.Row>
136
+ </Grid>
137
+ </Modal>
138
+ )}
139
+ </Fragment>
140
+ ))}
141
+ </Grid>
142
+ </section>
143
+ </article>
144
+ </Container>
145
+ );
146
+ };
187
147
 
188
- /**
189
- * Property types.
190
- * @property {Object} propTypes Property types.
191
- * @static
192
- */
193
148
  AlbumView.propTypes = {
194
149
  /**
195
150
  * Content of the object
@@ -4,6 +4,7 @@ import { useHistory } from 'react-router-dom';
4
4
  import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers';
5
5
  import { Container as SemanticContainer } from 'semantic-ui-react';
6
6
  import { UniversalLink } from '@plone/volto/components';
7
+ import { Redirect } from 'react-router-dom';
7
8
  import { FormattedMessage } from 'react-intl';
8
9
  import config from '@plone/volto/registry';
9
10
 
@@ -19,6 +20,9 @@ const LinkView = ({ token, content }) => {
19
20
  }
20
21
  }
21
22
  }, [content, history, token]);
23
+ if (__SERVER__ && !token && content.remoteUrl) {
24
+ return <Redirect to={content.remoteUrl} />;
25
+ }
22
26
  const { title, description, remoteUrl } = content;
23
27
  const { openExternalLinkInNewTab } = config.settings;
24
28
  const Container =
@@ -7,6 +7,8 @@ import LinkView from './LinkView';
7
7
 
8
8
  const mockStore = configureStore();
9
9
 
10
+ global.__SERVER__ = false; // eslint-disable-line no-underscore-dangle
11
+
10
12
  const store = mockStore({
11
13
  userSession: {
12
14
  token: null,
@@ -15,7 +15,6 @@ import qs from 'query-string';
15
15
  import {
16
16
  ContentMetadataTags,
17
17
  Comments,
18
- Tags,
19
18
  Toolbar,
20
19
  } from '@plone/volto/components';
21
20
  import { listActions, getContent } from '@plone/volto/actions';
@@ -256,11 +255,6 @@ class View extends Component {
256
255
  history={this.props.history}
257
256
  />
258
257
  <SlotRenderer name="belowContent" content={this.props.content} />
259
- {config.settings.showTags &&
260
- this.props.content.subjects &&
261
- this.props.content.subjects.length > 0 && (
262
- <Tags tags={this.props.content.subjects} />
263
- )}
264
258
  {this.props.content.allow_discussion && (
265
259
  <Comments pathname={this.props.pathname} />
266
260
  )}
@@ -19,6 +19,7 @@ import rulesSVG from '@plone/volto/icons/content-existing.svg';
19
19
  import undoControlPanelSVG from '@plone/volto/icons/undo-control-panel.svg';
20
20
  import linkSVG from '@plone/volto/icons/link.svg';
21
21
  import relationsSVG from '@plone/volto/icons/ahead.svg';
22
+ import config from '@plone/volto/registry';
22
23
 
23
24
  export const controlPanelsIcons = {
24
25
  default: settingsSVG,
@@ -53,62 +54,67 @@ export const filterControlPanels = (controlpanels = []) => {
53
54
  );
54
55
  };
55
56
 
57
+ export const unwantedControlPanelsFields = {
58
+ language: ['display_flags', 'always_show_selector'],
59
+ search: ['enable_livesearch'],
60
+ site: [
61
+ 'display_publication_date_in_byline',
62
+ 'icon_visibility',
63
+ 'thumb_visibility',
64
+ 'no_thumbs_portlet',
65
+ 'no_thumbs_lists',
66
+ 'no_thumbs_summary',
67
+ 'no_thumbs_tables',
68
+ 'thumb_scale_portlet',
69
+ 'thumb_scale_listing',
70
+ 'thumb_scale_table',
71
+ 'thumb_scale_summary',
72
+ 'toolbar_position',
73
+ 'toolbar_logo',
74
+ 'default_page',
75
+ 'site_favicon',
76
+ 'site_favicon_mimetype',
77
+ 'exposeDCMetaTags',
78
+ 'enable_sitemap',
79
+ 'robots_txt',
80
+ 'webstats_js',
81
+ ],
82
+ editing: ['available_editors', 'default_editor', 'ext_editor'],
83
+ imaging: [
84
+ 'highpixeldensity_scales',
85
+ 'quality_2x',
86
+ 'quality_3x',
87
+ 'picture_variants',
88
+ 'image_captioning',
89
+ ],
90
+ navigation: [
91
+ 'generate_tabs',
92
+ 'navigation_depth',
93
+ 'nonfolderish_tabs',
94
+ 'sort_tabs_on',
95
+ 'sort_tabs_reversed',
96
+ 'sitemap_depth',
97
+ ],
98
+ };
99
+
56
100
  // Filters props.controlpanel.schema to only valid/relevant fields
57
101
  export const filterControlPanelsSchema = (controlpanel) => {
58
102
  const panelType = controlpanel['@id'].split('/').pop();
59
103
 
60
- const unwantedSettings = {
61
- language: ['display_flags', 'always_show_selector'],
62
- search: ['enable_livesearch'],
63
- site: [
64
- 'display_publication_date_in_byline',
65
- 'icon_visibility',
66
- 'thumb_visibility',
67
- 'no_thumbs_portlet',
68
- 'no_thumbs_lists',
69
- 'no_thumbs_summary',
70
- 'no_thumbs_tables',
71
- 'thumb_scale_portlet',
72
- 'thumb_scale_listing',
73
- 'thumb_scale_table',
74
- 'thumb_scale_summary',
75
- 'toolbar_position',
76
- 'toolbar_logo',
77
- 'default_page',
78
- 'site_favicon',
79
- 'site_favicon_mimetype',
80
- 'exposeDCMetaTags',
81
- 'enable_sitemap',
82
- 'robots_txt',
83
- 'webstats_js',
84
- ],
85
- editing: ['available_editors', 'default_editor', 'ext_editor'],
86
- imaging: [
87
- 'highpixeldensity_scales',
88
- 'quality_2x',
89
- 'quality_3x',
90
- 'picture_variants',
91
- 'image_captioning',
92
- ],
93
- navigation: [
94
- 'generate_tabs',
95
- 'navigation_depth',
96
- 'sort_tabs_on',
97
- 'sort_tabs_reversed',
98
- 'sitemap_depth',
99
- ],
100
- };
104
+ const { unwantedControlPanelsFields } = config.settings;
101
105
 
102
106
  // Creates modified version of properties object
103
107
  const newPropertiesObj = Object.fromEntries(
104
108
  Object.entries(controlpanel.schema.properties).filter(
105
- ([key, val]) => !(unwantedSettings[panelType] || []).includes(key),
109
+ ([key, _val]) =>
110
+ !(unwantedControlPanelsFields[panelType] || []).includes(key),
106
111
  ),
107
112
  );
108
113
  // Filters props.controlpanel.schema.fieldsets.fields to only valid/relevant fields
109
114
  const filterFields = (fields) => {
110
115
  return fields.filter(
111
- (field) => !(unwantedSettings[panelType] || []).includes(field),
116
+ (field) =>
117
+ !(unwantedControlPanelsFields[panelType] || []).includes(field),
112
118
  );
113
119
  };
114
120
  // Creates modified version of fieldsets array
@@ -221,6 +221,7 @@ test('test navigation controlpanel fields', () => {
221
221
  const not_in_navigation = [
222
222
  'generate_tabs',
223
223
  'navigation_depth',
224
+ 'nonfolderish_tabs',
224
225
  'sort_tabs_on',
225
226
  'sort_tabs_reversed',
226
227
  'sitemap_depth',
@@ -18,6 +18,7 @@ import {
18
18
  import { components } from './Components';
19
19
  import { loadables } from './Loadables';
20
20
  import { workflowMapping } from './Workflows';
21
+ import slots from './slots';
21
22
 
22
23
  import { contentIcons } from './ContentIcons';
23
24
  import { styleClassNameConverters, styleClassNameExtenders } from './Style';
@@ -25,6 +26,7 @@ import {
25
26
  controlPanelsIcons,
26
27
  filterControlPanels,
27
28
  filterControlPanelsSchema,
29
+ unwantedControlPanelsFields,
28
30
  } from './ControlPanels';
29
31
 
30
32
  import applyAddonConfiguration, { addonsInfo } from 'load-volto-addons';
@@ -153,6 +155,7 @@ let config = {
153
155
  controlPanelsIcons,
154
156
  filterControlPanels,
155
157
  filterControlPanelsSchema,
158
+ unwantedControlPanelsFields,
156
159
  externalRoutes: [
157
160
  // URL to be considered as external
158
161
  // {
@@ -168,6 +171,7 @@ let config = {
168
171
  ],
169
172
  showSelfRegistration: false,
170
173
  contentMetadataTagsImageField: 'image',
174
+ contentPropertiesSchemaEnhancer: null,
171
175
  hasWorkingCopySupport: false,
172
176
  maxUndoLevels: 200, // undo history size for the main form
173
177
  addonsInfo: addonsInfo,
@@ -242,6 +246,18 @@ ConfigRegistry.components = config.components;
242
246
  ConfigRegistry.slots = config.slots;
243
247
  ConfigRegistry.utilities = config.utilities;
244
248
 
249
+ // Register slots
250
+ Object.entries(slots).forEach(([slotName, components]) => {
251
+ components.forEach(({ name, component, predicates = [] }) => {
252
+ ConfigRegistry.registerSlotComponent({
253
+ slot: slotName,
254
+ name,
255
+ component,
256
+ predicates,
257
+ });
258
+ });
259
+ });
260
+
245
261
  registerValidators(ConfigRegistry);
246
262
 
247
263
  applyAddonConfiguration(ConfigRegistry);
@@ -0,0 +1,12 @@
1
+ import { Tags } from '@plone/volto/components';
2
+
3
+ const slots = {
4
+ belowContent: [
5
+ {
6
+ name: 'tags',
7
+ component: Tags,
8
+ },
9
+ ],
10
+ };
11
+
12
+ export default slots;