@plone/volto 18.0.0-alpha.41 → 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 (187) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/finalreleasechangelog.py +48 -0
  3. package/locales/ca/LC_MESSAGES/volto.po +39 -13
  4. package/locales/ca.json +1 -1
  5. package/locales/de/LC_MESSAGES/volto.po +40 -14
  6. package/locales/de.json +1 -1
  7. package/locales/en/LC_MESSAGES/volto.po +39 -13
  8. package/locales/en.json +1 -1
  9. package/locales/es/LC_MESSAGES/volto.po +40 -14
  10. package/locales/es.json +1 -1
  11. package/locales/eu/LC_MESSAGES/volto.po +40 -14
  12. package/locales/eu.json +1 -1
  13. package/locales/fi/LC_MESSAGES/volto.po +40 -14
  14. package/locales/fi.json +1 -1
  15. package/locales/fr/LC_MESSAGES/volto.po +40 -14
  16. package/locales/fr.json +1 -1
  17. package/locales/hi/LC_MESSAGES/volto.po +40 -14
  18. package/locales/hi.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +40 -14
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +39 -13
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +39 -13
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +39 -13
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +40 -14
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +39 -13
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +40 -14
  32. package/locales/zh_CN/LC_MESSAGES/volto.po +40 -14
  33. package/locales/zh_CN.json +1 -1
  34. package/package.json +5 -6
  35. package/razzle.config.js +3 -3
  36. package/src/components/index.js +0 -1
  37. package/src/components/manage/Actions/Actions.stories.jsx +138 -0
  38. package/src/components/manage/Add/Add.jsx +7 -4
  39. package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
  40. package/src/components/manage/Blocks/Block/BlocksForm.jsx +5 -0
  41. package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
  42. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
  43. package/src/components/manage/Blocks/Block/Order/Item.jsx +8 -2
  44. package/src/components/manage/Blocks/Block/Order/Order.jsx +2 -0
  45. package/src/components/manage/Blocks/Container/Data.jsx +10 -2
  46. package/src/components/manage/Blocks/Grid/View.jsx +3 -0
  47. package/src/components/manage/Blocks/Image/ImageSidebar.jsx +10 -2
  48. package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
  49. package/src/components/manage/Blocks/Listing/ListingData.jsx +10 -2
  50. package/src/components/manage/Blocks/Maps/MapsSidebar.jsx +3 -1
  51. package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +2 -0
  52. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +18 -2
  53. package/src/components/manage/Blocks/Search/components/SortOn.jsx +82 -55
  54. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +1 -1
  55. package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
  56. package/src/components/manage/Blocks/Teaser/Data.jsx +10 -2
  57. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
  58. package/src/components/manage/Blocks/ToC/Edit.jsx +36 -28
  59. package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
  60. package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
  61. package/src/components/manage/Blocks/Video/VideoSidebar.jsx +3 -1
  62. package/src/components/manage/Contents/Contents.jsx +4 -1
  63. package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
  64. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
  65. package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
  66. package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
  67. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
  68. package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
  69. package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
  70. package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -0
  71. package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
  72. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
  73. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
  74. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
  75. package/src/components/manage/Controlpanels/UndoControlpanel.jsx +3 -3
  76. package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +28 -12
  77. package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +12 -4
  78. package/src/components/manage/Display/Display.jsx +92 -148
  79. package/src/components/manage/Display/Display.stories.jsx +46 -0
  80. package/src/components/manage/Edit/Edit.jsx +2 -4
  81. package/src/components/manage/Form/Form.jsx +85 -20
  82. package/src/components/manage/Form/InlineForm.jsx +2 -4
  83. package/src/components/manage/Form/ModalForm.jsx +1 -1
  84. package/src/components/manage/History/History.jsx +1 -1
  85. package/src/components/manage/Pluggable/Pluggable.test.js +1 -1
  86. package/src/components/manage/Preferences/ChangePassword.jsx +94 -172
  87. package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
  88. package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
  89. package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
  90. package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
  91. package/src/components/manage/Toolbar/More.jsx +308 -399
  92. package/src/components/manage/Toolbar/Toolbar.jsx +1 -1
  93. package/src/components/manage/Widgets/ArrayWidget.jsx +2 -2
  94. package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
  95. package/src/components/manage/Widgets/ImageWidget.jsx +6 -5
  96. package/src/components/manage/Widgets/RecurrenceWidget/EndField.jsx +7 -1
  97. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +80 -31
  98. package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
  99. package/src/components/theme/Register/Register.jsx +70 -142
  100. package/src/components/theme/Register/Register.stories.jsx +49 -0
  101. package/src/components/theme/Search/Search.jsx +13 -5
  102. package/src/components/theme/Tags/Tags.jsx +19 -10
  103. package/src/components/theme/Tags/Tags.test.jsx +9 -11
  104. package/src/components/theme/View/AlbumView.jsx +122 -167
  105. package/src/components/theme/View/LinkView.jsx +4 -0
  106. package/src/components/theme/View/LinkView.test.jsx +2 -0
  107. package/src/components/theme/View/View.jsx +0 -13
  108. package/src/components/theme/View/View.test.jsx +0 -3
  109. package/src/config/ControlPanels.js +49 -43
  110. package/src/config/Widgets.jsx +1 -1
  111. package/src/config/config.test.js +1 -0
  112. package/src/config/index.js +23 -2
  113. package/src/config/slots.js +12 -0
  114. package/src/config/validation.ts +155 -0
  115. package/src/helpers/Blocks/Blocks.js +12 -7
  116. package/src/helpers/Blocks/Blocks.test.js +15 -0
  117. package/src/helpers/Blocks/cloneBlocks.ts +1 -1
  118. package/src/helpers/Extensions/withBlockExtensions.jsx +1 -1
  119. package/src/helpers/FormValidation/FormValidation.jsx +128 -172
  120. package/src/helpers/FormValidation/FormValidation.test.js +836 -8
  121. package/src/helpers/FormValidation/validators.ts +203 -0
  122. package/src/helpers/MessageLabels/MessageLabels.js +28 -0
  123. package/src/helpers/Url/Url.test.js +19 -6
  124. package/src/helpers/Url/urlRegex.js +1 -1
  125. package/src/helpers/User/User.js +1 -1
  126. package/src/helpers/index.js +2 -0
  127. package/src/hooks/client/useClient.js +1 -1
  128. package/src/middleware/api.js +4 -2
  129. package/src/middleware/index.js +1 -0
  130. package/src/middleware/userSessionReset.js +46 -0
  131. package/src/store.js +2 -0
  132. package/test-setup-config.jsx +10 -0
  133. package/theme/themes/default/modules/embed.variables +1 -1
  134. package/theme/themes/pastanaga/collections/form.overrides +34 -0
  135. package/theme/themes/pastanaga/extras/blocks.less +6 -0
  136. package/theme/themes/pastanaga/extras/sidebar.less +4 -0
  137. package/theme/themes/pastanaga/extras/toolbar.less +10 -3
  138. package/tsconfig.declarations.json +3 -2
  139. package/types/components/index.d.ts +0 -1
  140. package/types/components/manage/Actions/Actions.stories.d.ts +8 -0
  141. package/types/components/manage/Blocks/Block/Order/Order.d.ts +2 -1
  142. package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
  143. package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
  144. package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
  145. package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
  146. package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
  147. package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
  148. package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
  149. package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
  150. package/types/components/manage/Contents/index.d.ts +1 -1
  151. package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
  152. package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
  153. package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
  154. package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
  155. package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
  156. package/types/components/manage/Controlpanels/index.d.ts +4 -4
  157. package/types/components/manage/Display/Display.stories.d.ts +8 -0
  158. package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
  159. package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
  160. package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
  161. package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
  162. package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
  163. package/types/components/manage/Toolbar/More.d.ts +8 -5
  164. package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
  165. package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
  166. package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
  167. package/types/components/manage/Widgets/index.d.ts +1 -1
  168. package/types/components/theme/Register/Register.d.ts +2 -2
  169. package/types/components/theme/Register/Register.stories.d.ts +9 -0
  170. package/types/components/theme/Tags/Tags.d.ts +15 -7
  171. package/types/components/theme/View/AlbumView.d.ts +3 -17
  172. package/types/config/ControlPanels.d.ts +8 -0
  173. package/types/config/RichTextEditor/ToHTML.d.ts +1 -1
  174. package/types/config/Widgets.d.ts +3 -3
  175. package/types/config/slots.d.ts +21 -0
  176. package/types/config/validation.d.ts +3 -0
  177. package/types/helpers/Blocks/Blocks.d.ts +6 -0
  178. package/types/helpers/Extensions/withBlockExtensions.d.ts +1 -1
  179. package/types/helpers/FormValidation/FormValidation.d.ts +2 -0
  180. package/types/helpers/FormValidation/validators.d.ts +29 -0
  181. package/types/helpers/MessageLabels/MessageLabels.d.ts +36 -0
  182. package/types/helpers/User/User.d.ts +1 -1
  183. package/types/helpers/index.d.ts +2 -2
  184. package/types/middleware/index.d.ts +1 -0
  185. package/types/middleware/userSessionReset.d.ts +5 -0
  186. package/src/components/theme/SocialSharing/SocialSharing.jsx +0 -48
  187. package/src/components/theme/SocialSharing/SocialSharing.test.jsx +0 -14
@@ -71,6 +71,7 @@ class Search extends Component {
71
71
 
72
72
  constructor(props) {
73
73
  super(props);
74
+ this.defaultPageSize = config.settings.defaultPageSize;
74
75
  this.state = { currentPage: 1, isClient: false, active: 'relevance' };
75
76
  }
76
77
 
@@ -109,19 +110,24 @@ class Search extends Component {
109
110
  const options = qs.parse(this.props.history.location.search);
110
111
  this.setState({ currentPage: 1 });
111
112
  options['use_site_search_settings'] = 1;
112
- this.props.searchContent('', options);
113
+ this.props.searchContent('', {
114
+ b_size: this.defaultPageSize,
115
+ ...options,
116
+ });
113
117
  };
114
118
 
115
119
  handleQueryPaginationChange = (e, { activePage }) => {
116
- const { settings } = config;
117
120
  window.scrollTo(0, 0);
118
121
  let options = qs.parse(this.props.history.location.search);
119
122
  options['use_site_search_settings'] = 1;
120
123
 
121
124
  this.setState({ currentPage: activePage }, () => {
122
125
  this.props.searchContent('', {
126
+ b_size: this.defaultPageSize,
123
127
  ...options,
124
- b_start: (this.state.currentPage - 1) * settings.defaultPageSize,
128
+ b_start:
129
+ (this.state.currentPage - 1) *
130
+ (options.b_size || this.defaultPageSize),
125
131
  });
126
132
  });
127
133
  };
@@ -149,7 +155,8 @@ class Search extends Component {
149
155
  * @returns {string} Markup for the component.
150
156
  */
151
157
  render() {
152
- const { settings } = config;
158
+ const options = qs.parse(this.props.history.location.search);
159
+
153
160
  return (
154
161
  <Container id="page-search">
155
162
  <Helmet title={this.props.intl.formatMessage(messages.Search)} />
@@ -282,7 +289,8 @@ class Search extends Component {
282
289
  <Pagination
283
290
  activePage={this.state.currentPage}
284
291
  totalPages={Math.ceil(
285
- this.props.search.items_total / settings.defaultPageSize,
292
+ this.props.search.items_total /
293
+ (options.b_size || this.defaultPageSize),
286
294
  )}
287
295
  onPageChange={this.handleQueryPaginationChange}
288
296
  firstItem={null}
@@ -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,18 +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
- {/* Add opt-in social sharing if required, disabled by default */}
265
- {/* In the future this might be parameterized from the app config */}
266
- {/* <SocialSharing
267
- url={typeof window === 'undefined' ? '' : window.location.href}
268
- title={this.props.content.title}
269
- description={this.props.content.description || ''}
270
- /> */}
271
258
  {this.props.content.allow_discussion && (
272
259
  <Comments pathname={this.props.pathname} />
273
260
  )}
@@ -30,9 +30,6 @@ jest.mock('../../manage/Toolbar/Toolbar', () =>
30
30
  jest.fn(() => <div id="Portal" />),
31
31
  );
32
32
 
33
- jest.mock('../SocialSharing/SocialSharing', () =>
34
- jest.fn(() => <div id="SocialSharing" />),
35
- );
36
33
  jest.mock('../Comments/Comments', () => jest.fn(() => <div id="Comments" />));
37
34
  jest.mock('../Tags/Tags', () => jest.fn(() => <div id="Tags" />));
38
35
  jest.mock('../SlotRenderer/SlotRenderer', () =>
@@ -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