@plone/volto 17.0.0-alpha.2 → 17.0.0-alpha.21

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 (318) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/CHANGELOG.md +549 -15
  3. package/CONTRIBUTING.md +1 -1
  4. package/README.md +11 -14
  5. package/addon-registry.js +34 -0
  6. package/create-theme-addons-loader.js +79 -0
  7. package/cypress/support/commands.js +58 -5
  8. package/cypress/support/e2e.js +1 -2
  9. package/cypress/support/volto-slate.js +4 -5
  10. package/docker-compose.yml +1 -1
  11. package/locales/ca/LC_MESSAGES/volto.po +282 -7
  12. package/locales/ca.json +1 -1
  13. package/locales/de/LC_MESSAGES/volto.po +301 -26
  14. package/locales/de.json +1 -1
  15. package/locales/en/LC_MESSAGES/volto.po +281 -6
  16. package/locales/en.json +1 -1
  17. package/locales/es/LC_MESSAGES/volto.po +291 -16
  18. package/locales/es.json +1 -1
  19. package/locales/eu/LC_MESSAGES/volto.po +282 -7
  20. package/locales/eu.json +1 -1
  21. package/locales/fi/LC_MESSAGES/volto.po +4891 -0
  22. package/locales/fi.json +1 -1
  23. package/locales/fr/LC_MESSAGES/volto.po +282 -7
  24. package/locales/fr.json +1 -1
  25. package/locales/it/LC_MESSAGES/volto.po +284 -9
  26. package/locales/it.json +1 -1
  27. package/locales/ja/LC_MESSAGES/volto.po +282 -7
  28. package/locales/ja.json +1 -1
  29. package/locales/nl/LC_MESSAGES/volto.po +937 -650
  30. package/locales/nl.json +1 -1
  31. package/locales/pt/LC_MESSAGES/volto.po +282 -7
  32. package/locales/pt.json +1 -1
  33. package/locales/pt_BR/LC_MESSAGES/volto.po +291 -16
  34. package/locales/pt_BR.json +1 -1
  35. package/locales/ro/LC_MESSAGES/volto.po +282 -7
  36. package/locales/ro.json +1 -1
  37. package/locales/volto.pot +282 -7
  38. package/locales/zh_CN/LC_MESSAGES/volto.po +282 -7
  39. package/locales/zh_CN.json +1 -1
  40. package/package.json +8 -6
  41. package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +1 -1
  42. package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +1 -1
  43. package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +1 -1
  44. package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +1 -1
  45. package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +1 -1
  46. package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +1 -1
  47. package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +1 -1
  48. package/packages/volto-slate/build/messages/src/elementEditor/messages.json +1 -1
  49. package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +1 -1
  50. package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +1 -1
  51. package/packages/volto-slate/package.json +1 -1
  52. package/packages/volto-slate/src/actions/index.js +1 -1
  53. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.jsx +21 -212
  54. package/packages/volto-slate/src/blocks/Table/schema.js +122 -0
  55. package/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx +8 -3
  56. package/packages/volto-slate/src/blocks/Text/SlashMenu.jsx +4 -3
  57. package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +20 -16
  58. package/packages/volto-slate/src/blocks/Text/extensions/withDeserializers.js +3 -1
  59. package/packages/volto-slate/src/blocks/Text/index.js +10 -2
  60. package/packages/volto-slate/src/editor/config.jsx +5 -4
  61. package/packages/volto-slate/src/editor/deserialize.js +0 -1
  62. package/packages/volto-slate/src/editor/index.js +4 -4
  63. package/packages/volto-slate/src/editor/less/slate.less +28 -0
  64. package/packages/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx +14 -4
  65. package/packages/volto-slate/src/editor/plugins/StyleMenu/utils.js +14 -5
  66. package/packages/volto-slate/src/editor/render.jsx +68 -8
  67. package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +2 -2
  68. package/packages/volto-slate/src/editor/ui/index.js +15 -15
  69. package/packages/volto-slate/src/index.js +2 -2
  70. package/packages/volto-slate/src/utils/blocks.js +7 -0
  71. package/packages/volto-slate/src/widgets/RichTextWidget.jsx +15 -8
  72. package/razzle.config.js +28 -0
  73. package/src/actions/index.js +6 -0
  74. package/src/actions/language/language.js +9 -8
  75. package/src/actions/querystringsearch/querystringsearch.js +20 -14
  76. package/src/actions/relations/rebuild.js +25 -0
  77. package/src/actions/relations/relations.js +86 -0
  78. package/src/actions/relations/relations.test.js +15 -0
  79. package/src/components/index.js +3 -0
  80. package/src/components/manage/Add/Add.jsx +2 -2
  81. package/src/components/manage/AnchorPlugin/index.jsx +2 -2
  82. package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +3 -1
  83. package/src/components/manage/BlockChooser/BlockChooser.jsx +14 -5
  84. package/src/components/manage/BlockChooser/BlockChooser.test.jsx +5 -0
  85. package/src/components/manage/Blocks/Block/BlocksForm.jsx +19 -2
  86. package/src/components/manage/Blocks/Block/Edit.jsx +1 -1
  87. package/src/components/manage/Blocks/Block/Style.jsx +2 -2
  88. package/src/components/manage/Blocks/Container/Data.jsx +32 -0
  89. package/src/components/manage/Blocks/Container/Edit.jsx +174 -0
  90. package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +120 -0
  91. package/src/components/manage/Blocks/Container/NewBlockAddButton.jsx +84 -0
  92. package/src/components/manage/Blocks/Container/SimpleContainerToolbar.jsx +54 -0
  93. package/src/components/manage/Blocks/Grid/Edit.jsx +33 -0
  94. package/src/components/manage/Blocks/Grid/View.jsx +43 -0
  95. package/src/components/manage/Blocks/Grid/adapter.js +14 -0
  96. package/src/components/manage/Blocks/Grid/grid-1.svg +6 -0
  97. package/src/components/manage/Blocks/Grid/grid-2.svg +9 -0
  98. package/src/components/manage/Blocks/Grid/grid-3.svg +10 -0
  99. package/src/components/manage/Blocks/Grid/grid-4.svg +11 -0
  100. package/src/components/manage/Blocks/Grid/schema.js +35 -0
  101. package/src/components/manage/Blocks/Grid/templates.js +47 -0
  102. package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +6 -1
  103. package/src/components/manage/Blocks/Image/Edit.jsx +51 -12
  104. package/src/components/manage/Blocks/Image/Edit.test.jsx +2 -0
  105. package/src/components/manage/Blocks/Image/ImageSidebar.jsx +66 -16
  106. package/src/components/manage/Blocks/Image/View.jsx +25 -5
  107. package/src/components/manage/Blocks/Image/View.test.jsx +20 -0
  108. package/src/components/manage/Blocks/Image/schema.js +12 -9
  109. package/src/components/manage/Blocks/Image/utils.js +14 -0
  110. package/src/components/manage/Blocks/LeadImage/Edit.jsx +32 -10
  111. package/src/components/manage/Blocks/LeadImage/Edit.test.jsx +11 -1
  112. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +28 -9
  113. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -2
  114. package/src/components/manage/Blocks/LeadImage/View.jsx +50 -38
  115. package/src/components/manage/Blocks/LeadImage/View.test.jsx +11 -1
  116. package/src/components/manage/Blocks/Listing/DefaultTemplate.jsx +18 -3
  117. package/src/components/manage/Blocks/Listing/Edit.jsx +0 -14
  118. package/src/components/manage/Blocks/Listing/ListingBody.jsx +30 -8
  119. package/src/components/manage/Blocks/Listing/ListingBody.test.jsx +20 -0
  120. package/src/components/manage/Blocks/Listing/SummaryTemplate.jsx +1 -1
  121. package/src/components/manage/Blocks/Listing/getAsyncData.js +9 -3
  122. package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +26 -18
  123. package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +5 -4
  124. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +2 -1
  125. package/src/components/manage/Blocks/Search/components/DateRangeFacet.jsx +4 -1
  126. package/src/components/manage/Blocks/Search/components/Facets.jsx +64 -4
  127. package/src/components/manage/Blocks/Search/components/SearchInput.jsx +9 -2
  128. package/src/components/manage/Blocks/Search/components/index.js +13 -13
  129. package/src/components/manage/Blocks/Search/hocs/index.js +2 -2
  130. package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +2 -2
  131. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +43 -15
  132. package/src/components/manage/Blocks/Search/layout/LeftColumnFacets.jsx +17 -5
  133. package/src/components/manage/Blocks/Search/layout/RightColumnFacets.jsx +17 -5
  134. package/src/components/manage/Blocks/Search/layout/TopSideFacets.jsx +21 -5
  135. package/src/components/manage/Blocks/Search/schema.js +16 -1
  136. package/src/components/manage/Blocks/Teaser/Body.jsx +0 -1
  137. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +5 -10
  138. package/src/components/manage/Blocks/Teaser/schema.js +5 -0
  139. package/src/components/manage/Blocks/Title/View.jsx +15 -5
  140. package/src/components/manage/Blocks/Title/View.test.jsx +16 -1
  141. package/src/components/manage/Blocks/ToC/Schema.jsx +5 -1
  142. package/src/components/manage/Blocks/ToC/View.jsx +8 -1
  143. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +17 -4
  144. package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +148 -10
  145. package/src/components/manage/Blocks/ToC/variations/index.js +3 -1
  146. package/src/components/manage/Contents/Contents.jsx +47 -32
  147. package/src/components/manage/Contents/ContentsItem.jsx +6 -0
  148. package/src/components/manage/Contents/ContentsUploadModal.jsx +10 -5
  149. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +3 -3
  150. package/src/components/manage/Controlpanels/Controlpanels.jsx +199 -224
  151. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +46 -7
  152. package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +66 -0
  153. package/src/components/manage/Controlpanels/Relations/Relations.jsx +114 -0
  154. package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +479 -0
  155. package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +531 -0
  156. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.jsx +3 -3
  157. package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +51 -82
  158. package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +79 -75
  159. package/src/components/manage/DragDropList/DragDropList.jsx +18 -13
  160. package/src/components/manage/Form/Form.jsx +5 -3
  161. package/src/components/manage/Form/InlineForm.jsx +39 -9
  162. package/src/components/manage/Form/InlineFormState.js +8 -0
  163. package/src/components/manage/History/History.jsx +11 -1
  164. package/src/components/manage/LinksToItem/LinksToItem.jsx +209 -0
  165. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +97 -0
  166. package/src/components/manage/Multilingual/CreateTranslation.jsx +2 -2
  167. package/src/components/manage/Multilingual/TranslationObject.jsx +4 -3
  168. package/src/components/manage/Preferences/ChangePassword.jsx +2 -2
  169. package/src/components/manage/Preferences/PersonalPreferences.jsx +2 -2
  170. package/src/components/manage/Sharing/Sharing.jsx +5 -1
  171. package/src/components/manage/Sidebar/AlignBlock.jsx +1 -1
  172. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +38 -0
  173. package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +34 -0
  174. package/src/components/manage/TemplateChooser/template.svg +10 -0
  175. package/src/components/manage/Toast/Toast.jsx +2 -2
  176. package/src/components/manage/Toolbar/More.jsx +15 -0
  177. package/src/components/manage/Toolbar/Types.jsx +2 -2
  178. package/src/components/manage/UniversalLink/UniversalLink.jsx +2 -6
  179. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +36 -0
  180. package/src/components/manage/Widgets/ColorPickerWidget.jsx +6 -1
  181. package/src/components/manage/Widgets/DatetimeWidget.jsx +9 -5
  182. package/src/components/manage/Widgets/FileWidget.jsx +2 -1
  183. package/src/components/manage/Widgets/ObjectListWidget.jsx +3 -8
  184. package/src/components/manage/Widgets/RecurrenceWidget/ByDayField.jsx +2 -1
  185. package/src/components/manage/Widgets/RecurrenceWidget/MonthOfTheYearField.jsx +2 -1
  186. package/src/components/manage/Widgets/RecurrenceWidget/Occurences.jsx +2 -1
  187. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +8 -3
  188. package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthField.jsx +2 -1
  189. package/src/components/manage/Widgets/SelectUtils.js +1 -1
  190. package/src/components/manage/Widgets/SelectWidget.jsx +1 -1
  191. package/src/components/theme/Anontools/Anontools.jsx +44 -72
  192. package/src/components/theme/Anontools/Anontools.stories.jsx +16 -6
  193. package/src/components/theme/Anontools/Anontools.test.jsx +16 -2
  194. package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +52 -99
  195. package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.jsx +14 -13
  196. package/src/components/theme/Comments/CommentEditModal.jsx +63 -115
  197. package/src/components/theme/Component/Component.jsx +1 -1
  198. package/src/components/theme/ContactForm/ContactForm.jsx +108 -192
  199. package/src/components/theme/ContactForm/ContactForm.stories.jsx +1 -1
  200. package/src/components/theme/ContactForm/ContactForm.test.jsx +2 -3
  201. package/src/components/theme/Footer/Footer.jsx +2 -13
  202. package/src/components/theme/Header/Header.jsx +37 -63
  203. package/src/components/theme/Header/Header.test.jsx +18 -0
  204. package/src/components/theme/Icon/Icon.jsx +2 -2
  205. package/src/components/theme/Image/Image.jsx +96 -0
  206. package/src/components/theme/Image/Image.test.jsx +125 -0
  207. package/src/components/theme/LanguageSelector/LanguageSelector.js +8 -3
  208. package/src/components/theme/Login/Login.jsx +1 -0
  209. package/src/components/theme/Logo/Logo.jsx +4 -1
  210. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +2 -2
  211. package/src/components/theme/Navigation/NavItem.jsx +4 -2
  212. package/src/components/theme/NotFound/NotFound.jsx +55 -41
  213. package/src/components/theme/PasswordReset/PasswordReset.jsx +7 -4
  214. package/src/components/theme/PasswordReset/RequestPasswordReset.jsx +1 -1
  215. package/src/components/theme/PreviewImage/PreviewImage.jsx +25 -14
  216. package/src/components/theme/PreviewImage/PreviewImage.test.js +39 -16
  217. package/src/components/theme/SearchWidget/SearchWidget.jsx +38 -98
  218. package/src/components/theme/Sitemap/Sitemap.jsx +5 -3
  219. package/src/components/theme/View/AlbumView.jsx +20 -16
  220. package/src/components/theme/View/DefaultView.jsx +1 -1
  221. package/src/components/theme/View/EventDatesInfo.jsx +2 -1
  222. package/src/components/theme/View/EventView.jsx +36 -25
  223. package/src/components/theme/View/FileView.jsx +23 -18
  224. package/src/components/theme/View/ImageView.jsx +40 -32
  225. package/src/components/theme/View/ImageView.test.jsx +4 -0
  226. package/src/components/theme/View/LinkView.jsx +53 -78
  227. package/src/components/theme/View/ListingView.jsx +36 -28
  228. package/src/components/theme/View/NewsItemView.jsx +16 -17
  229. package/src/components/theme/View/RenderBlocks.jsx +56 -21
  230. package/src/components/theme/View/RenderEmptyBlock.jsx +5 -0
  231. package/src/components/theme/View/SummaryView.jsx +49 -39
  232. package/src/components/theme/View/TabularView.jsx +59 -53
  233. package/src/components/theme/Widgets/DateWidget.jsx +2 -1
  234. package/src/components/theme/Widgets/DatetimeWidget.jsx +2 -1
  235. package/src/components/theme/Widgets/RelationsWidget.jsx +13 -11
  236. package/src/config/Blocks.jsx +46 -0
  237. package/src/config/Components.jsx +2 -1
  238. package/src/config/ControlPanels.js +2 -0
  239. package/src/config/NonContentRoutes.jsx +1 -0
  240. package/src/config/RichTextEditor/Blocks.jsx +2 -2
  241. package/src/config/RichTextEditor/FromHTML.jsx +2 -2
  242. package/src/config/RichTextEditor/Styles.jsx +1 -1
  243. package/src/config/Widgets.jsx +2 -0
  244. package/src/config/index.js +24 -0
  245. package/src/config/server.js +2 -0
  246. package/src/constants/ActionTypes.js +4 -0
  247. package/src/constants/Indexes.js +3 -1
  248. package/src/constants/Languages.js +8 -4
  249. package/src/express-middleware/devproxy.js +1 -1
  250. package/src/express-middleware/files.js +3 -3
  251. package/src/express-middleware/images.js +4 -4
  252. package/src/express-middleware/ok.js +16 -0
  253. package/src/express-middleware/robotstxt.js +1 -1
  254. package/src/express-middleware/sitemap.js +37 -5
  255. package/src/express-middleware/static.js +3 -3
  256. package/src/helpers/Api/Api.js +1 -1
  257. package/src/helpers/Blocks/Blocks.js +48 -0
  258. package/src/helpers/Blocks/Blocks.test.js +79 -0
  259. package/src/helpers/Extensions/index.js +2 -1
  260. package/src/helpers/Extensions/withBlockSchemaEnhancer.js +15 -11
  261. package/src/helpers/Extensions/withBlockSchemaEnhancer.test.js +145 -0
  262. package/src/helpers/FormValidation/FormValidation.js +40 -2
  263. package/src/helpers/FormValidation/FormValidation.test.js +73 -0
  264. package/src/helpers/Html/Html.jsx +3 -1
  265. package/src/helpers/Html/Html.test.jsx +5 -0
  266. package/src/helpers/MessageLabels/MessageLabels.js +80 -0
  267. package/src/helpers/Robots/Robots.js +24 -6
  268. package/src/helpers/ScrollToTop/ScrollToTop.jsx +5 -3
  269. package/src/helpers/Sitemap/Sitemap.js +44 -2
  270. package/src/helpers/Url/Url.js +49 -7
  271. package/src/helpers/Url/Url.test.js +67 -0
  272. package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +191 -0
  273. package/src/helpers/Utils/Utils.js +63 -13
  274. package/src/helpers/Utils/Utils.test.js +4 -4
  275. package/src/helpers/Utils/usePagination.js +67 -14
  276. package/src/helpers/Utils/usePagination.test.js +115 -0
  277. package/src/helpers/index.js +20 -10
  278. package/src/hooks/client/useClient.js +11 -0
  279. package/src/hooks/clipboard/useClipboard.js +26 -0
  280. package/src/hooks/index.js +2 -0
  281. package/src/icons/grid-block.svg +11 -0
  282. package/src/middleware/Api.test.js +54 -0
  283. package/src/middleware/api.js +24 -6
  284. package/src/middleware/index.js +2 -2
  285. package/src/reducers/actions/actions.js +8 -6
  286. package/src/reducers/actions/actions.test.js +70 -0
  287. package/src/reducers/breadcrumbs/breadcrumbs.js +1 -1
  288. package/src/reducers/index.js +2 -0
  289. package/src/reducers/navigation/navigation.js +1 -1
  290. package/src/reducers/relations/relations.js +173 -0
  291. package/src/reducers/types/types.js +1 -1
  292. package/src/routes.js +14 -0
  293. package/src/server.jsx +28 -23
  294. package/src/start-server.js +2 -2
  295. package/test-setup-config.js +11 -1
  296. package/theme/themes/pastanaga/extras/blocks.less +5 -1
  297. package/theme/themes/pastanaga/extras/contents.less +1 -0
  298. package/theme/themes/pastanaga/extras/grid.less +426 -0
  299. package/theme/themes/pastanaga/extras/main.less +8 -1
  300. package/theme/themes/pastanaga/extras/search.less +6 -0
  301. package/theme/themes/pastanaga/extras/sidebar.less +4 -0
  302. package/theme/themes/pastanaga/extras/toc.less +29 -0
  303. package/theme/themes/pastanaga/extras/userscontrolpanel.less +99 -76
  304. package/.changelog.draft +0 -31
  305. package/.editorconfig +0 -36
  306. package/.storybook/main.js +0 -127
  307. package/.storybook/manager.js +0 -15
  308. package/.storybook/preview.js +0 -21
  309. package/.storybook/static/previewImage.svg +0 -48
  310. package/.yarnrc.yml +0 -5
  311. package/jsdoc.json +0 -16
  312. package/netlify.toml +0 -5
  313. package/pyvenv.cfg +0 -3
  314. package/share/man/man1/ttx.1 +0 -225
  315. package/src/components/manage/Blocks/Teaser/utils.js +0 -44
  316. package/src/components/manage/Blocks/Teaser/utils.test.jsx +0 -229
  317. package/src/components/theme/Header/Header.md +0 -27
  318. package/towncrier.toml +0 -33
@@ -12,7 +12,7 @@ import { Message } from 'semantic-ui-react';
12
12
  import { isEqual } from 'lodash';
13
13
 
14
14
  import { LeadImageSidebar, SidebarPortal } from '@plone/volto/components';
15
- import { flattenToAppURL } from '@plone/volto/helpers';
15
+ import config from '@plone/volto/registry';
16
16
 
17
17
  import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
18
18
 
@@ -79,11 +79,17 @@ class Edit extends Component {
79
79
  * @returns {string} Markup for the component.
80
80
  */
81
81
  render() {
82
+ const Image = config.getComponent({ name: 'Image' }).component;
82
83
  const { data, properties } = this.props;
83
84
  const placeholder =
84
85
  this.props.data.placeholder ||
85
86
  this.props.intl.formatMessage(messages.ImageBlockInputPlaceholder);
86
87
 
88
+ const hasImage = !!properties.image;
89
+ const hasImageData = hasImage && !!properties.image.data;
90
+ const className = cx('responsive', { 'full-image': data.align === 'full' });
91
+ const altText = data.image_caption || properties.image_caption || '';
92
+
87
93
  return (
88
94
  <div
89
95
  className={cx(
@@ -94,7 +100,7 @@ class Edit extends Component {
94
100
  data.align,
95
101
  )}
96
102
  >
97
- {!properties.image && (
103
+ {!hasImage && (
98
104
  <Message>
99
105
  <center>
100
106
  <img src={imageBlockSVG} alt="" />
@@ -102,15 +108,31 @@ class Edit extends Component {
102
108
  </center>
103
109
  </Message>
104
110
  )}
105
- {properties.image && (
111
+ {hasImage && hasImageData && (
106
112
  <img
107
- className={cx({ 'full-width': data.align === 'full' })}
108
- src={
109
- properties.image.data
110
- ? `data:${properties.image['content-type']};base64,${properties.image.data}`
111
- : flattenToAppURL(properties.image.download)
112
- }
113
- alt={data.image_caption || ''}
113
+ className={className}
114
+ src={`data:${properties.image['content-type']};base64,${properties.image.data}`}
115
+ width={properties.image.width}
116
+ height={properties.image.height}
117
+ alt={altText}
118
+ style={{
119
+ aspectRatio: `${properties.image.width}/${properties.image.height}`,
120
+ }}
121
+ />
122
+ )}
123
+ {hasImage && !hasImageData && (
124
+ <Image
125
+ className={className}
126
+ item={properties}
127
+ imageField="image"
128
+ sizes={(() => {
129
+ if (data.align === 'full' || data.align === 'center')
130
+ return '100vw';
131
+ if (data.align === 'left' || data.align === 'right')
132
+ return '50vw';
133
+ return undefined;
134
+ })()}
135
+ alt={altText}
114
136
  />
115
137
  )}
116
138
  <SidebarPortal selected={this.props.selected}>
@@ -20,7 +20,17 @@ test('renders an edit Lead Image block component', () => {
20
20
  data={{}}
21
21
  properties={{
22
22
  image: {
23
- download: 'image.png',
23
+ download: 'http://localhost:3000/image.png',
24
+ width: 400,
25
+ height: 400,
26
+ scales: {
27
+ preview: {
28
+ download:
29
+ 'http://localhost:3000/image.png/@@images/image/image-400.png',
30
+ width: 400,
31
+ height: 400,
32
+ },
33
+ },
24
34
  },
25
35
  }}
26
36
  selected={false}
@@ -3,7 +3,12 @@ import PropTypes from 'prop-types';
3
3
  import { Form } from 'semantic-ui-react';
4
4
  import { Accordion, Grid, Segment } from 'semantic-ui-react';
5
5
  import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
6
- import { CheckboxWidget, Icon, TextWidget } from '@plone/volto/components';
6
+ import {
7
+ CheckboxWidget,
8
+ Icon,
9
+ Image,
10
+ TextWidget,
11
+ } from '@plone/volto/components';
7
12
  import { flattenToAppURL } from '@plone/volto/helpers';
8
13
  import AlignBlock from '@plone/volto/components/manage/Sidebar/AlignBlock';
9
14
 
@@ -90,14 +95,28 @@ const LeadImageSidebar = ({
90
95
  <>
91
96
  <Segment className="sidebar-metadata-container" secondary>
92
97
  {properties.image.filename}
93
- <img
94
- src={
95
- properties.image.data
96
- ? `data:${properties.image['content-type']};base64,${properties.image.data}`
97
- : flattenToAppURL(properties.image.scales.mini.download)
98
- }
99
- alt={properties.image_caption || ''}
100
- />
98
+ {properties.image.data && (
99
+ <img
100
+ // TODO understand when this actually happens
101
+ src={`data:${properties.image['content-type']};base64,${properties.image.data}`}
102
+ width={properties.image.width}
103
+ height={properties.image.height}
104
+ alt={data.image_caption || properties.image_caption || ''}
105
+ className="responsive"
106
+ style={{
107
+ aspectRatio: `${properties.image.width} / ${properties.image.height}`,
108
+ }}
109
+ />
110
+ )}
111
+ {!properties.image.data && (
112
+ <Image
113
+ item={properties}
114
+ imageField="image"
115
+ alt={data.image_caption || properties.image_caption || ''}
116
+ responsive={true}
117
+ sizes="188px"
118
+ />
119
+ )}
101
120
  </Segment>
102
121
  <Segment className="form sidebar-image-data">
103
122
  <TextWidget
@@ -20,9 +20,15 @@ test('renders a Lead Image block Sidebar component', () => {
20
20
  data={{}}
21
21
  properties={{
22
22
  image: {
23
+ download: 'http://localhost:3000/image.png',
24
+ width: 400,
25
+ height: 400,
23
26
  scales: {
24
- mini: {
25
- download: 'image.png',
27
+ preview: {
28
+ download:
29
+ 'http://localhost:3000/image.png/@@images/image/image-400.png',
30
+ width: 400,
31
+ height: 400,
26
32
  },
27
33
  },
28
34
  },
@@ -7,51 +7,63 @@ import React from 'react';
7
7
  import PropTypes from 'prop-types';
8
8
  import { UniversalLink } from '@plone/volto/components';
9
9
  import cx from 'classnames';
10
-
11
- import { flattenToAppURL } from '@plone/volto/helpers';
10
+ import config from '@plone/volto/registry';
12
11
 
13
12
  /**
14
13
  * View image block class.
15
14
  * @class View
16
15
  * @extends Component
17
16
  */
18
- const View = ({ data, properties }) => (
19
- <p
20
- className={cx(
21
- 'block image align',
22
- {
23
- center: !Boolean(data.align),
24
- },
25
- data.align,
26
- )}
27
- >
28
- {properties.image && (
29
- <>
30
- {(() => {
31
- const image = (
32
- <img
33
- className={cx({ 'full-width': data.align === 'full' })}
34
- src={flattenToAppURL(properties.image.download)}
35
- alt={properties.image_caption || ''}
36
- />
37
- );
38
- if (data.href) {
39
- return (
40
- <UniversalLink
41
- href={data.href}
42
- openLinkInNewTab={data.openLinkInNewTab}
43
- >
44
- {image}
45
- </UniversalLink>
17
+ const View = ({ data, properties }) => {
18
+ const Image = config.getComponent({ name: 'Image' }).component;
19
+
20
+ return (
21
+ <p
22
+ className={cx(
23
+ 'block image align',
24
+ {
25
+ center: !Boolean(data.align),
26
+ },
27
+ data.align,
28
+ )}
29
+ >
30
+ {properties.image && (
31
+ <>
32
+ {(() => {
33
+ const image = (
34
+ <Image
35
+ className={cx({ 'full-width': data.align === 'full' })}
36
+ item={properties}
37
+ imageField="image"
38
+ sizes={(() => {
39
+ if (data.align === 'full' || data.align === 'center')
40
+ return '100vw';
41
+ if (data.align === 'left' || data.align === 'right')
42
+ return '50vw';
43
+ return undefined;
44
+ })()}
45
+ alt={properties.image_caption || ''}
46
+ responsive={true}
47
+ />
46
48
  );
47
- } else {
48
- return image;
49
- }
50
- })()}
51
- </>
52
- )}
53
- </p>
54
- );
49
+ if (data.href) {
50
+ return (
51
+ <UniversalLink
52
+ href={data.href}
53
+ openLinkInNewTab={data.openLinkInNewTab}
54
+ >
55
+ {image}
56
+ </UniversalLink>
57
+ );
58
+ } else {
59
+ return image;
60
+ }
61
+ })()}
62
+ </>
63
+ )}
64
+ </p>
65
+ );
66
+ };
55
67
 
56
68
  /**
57
69
  * Property types.
@@ -8,7 +8,17 @@ test('renders a view image component', () => {
8
8
  data={{}}
9
9
  properties={{
10
10
  image: {
11
- download: 'image.png',
11
+ download: 'http://localhost:3000/image.png',
12
+ width: 400,
13
+ height: 400,
14
+ scales: {
15
+ preview: {
16
+ download:
17
+ 'http://localhost:3000/image.png/@@images/image/image-400.png',
18
+ width: 400,
19
+ height: 400,
20
+ },
21
+ },
12
22
  },
13
23
  }}
14
24
  />,
@@ -2,10 +2,15 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { ConditionalLink, UniversalLink } from '@plone/volto/components';
4
4
  import { flattenToAppURL } from '@plone/volto/helpers';
5
-
6
5
  import { isInternalURL } from '@plone/volto/helpers/Url/Url';
7
6
 
8
- const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
7
+ const DefaultTemplate = ({
8
+ headlineTag,
9
+ items,
10
+ linkTitle,
11
+ linkHref,
12
+ isEditMode,
13
+ }) => {
9
14
  let link = null;
10
15
  let href = linkHref?.[0]?.['@id'] || '';
11
16
 
@@ -19,6 +24,16 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
19
24
  link = <UniversalLink href={href}>{linkTitle || href}</UniversalLink>;
20
25
  }
21
26
 
27
+ const getTitleTag = (tag) => {
28
+ const level = tag.slice(-1);
29
+ if (/\d/.test(level)) {
30
+ return `h${Number(level) + 1}`;
31
+ } else {
32
+ return 'h3';
33
+ }
34
+ };
35
+ const TitleTag = headlineTag ? getTitleTag(headlineTag) : 'h3';
36
+
22
37
  return (
23
38
  <>
24
39
  <div className="items">
@@ -26,7 +41,7 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
26
41
  <div className="listing-item" key={item['@id']}>
27
42
  <ConditionalLink item={item} condition={!isEditMode}>
28
43
  <div className="listing-body">
29
- <h4>{item.title ? item.title : item.id}</h4>
44
+ <TitleTag>{item.title ? item.title : item.id}</TitleTag>
30
45
  <p>{item.description}</p>
31
46
  </div>
32
47
  </ConditionalLink>
@@ -26,21 +26,7 @@ const messages = defineMessages({
26
26
  const Edit = React.memo(
27
27
  (props) => {
28
28
  const { data, onChangeBlock, block, selected, pathname } = props;
29
-
30
29
  const intl = useIntl();
31
-
32
- // componentDidMount
33
- React.useEffect(() => {
34
- if (!data.query) {
35
- onChangeBlock(block, {
36
- ...data,
37
- query: [],
38
- block,
39
- });
40
- }
41
- /* eslint-disable react-hooks/exhaustive-deps */
42
- }, []);
43
-
44
30
  const placeholder =
45
31
  data.placeholder ||
46
32
  (data?.querystring?.query?.length
@@ -1,14 +1,35 @@
1
- import React, { createRef } from 'react';
1
+ import React, { createRef, useMemo } from 'react';
2
2
  import { FormattedMessage, injectIntl } from 'react-intl';
3
3
  import cx from 'classnames';
4
4
  import { Pagination, Dimmer, Loader } from 'semantic-ui-react';
5
+ import Slugger from 'github-slugger';
5
6
  import { Icon } from '@plone/volto/components';
7
+ import { renderLinkElement } from '@plone/volto-slate/editor/render';
6
8
  import config from '@plone/volto/registry';
7
9
  import withQuerystringResults from './withQuerystringResults';
8
10
 
9
11
  import paginationLeftSVG from '@plone/volto/icons/left-key.svg';
10
12
  import paginationRightSVG from '@plone/volto/icons/right-key.svg';
11
13
 
14
+ const Headline = ({ headlineTag, id, data = {}, listingItems, isEditMode }) => {
15
+ let attr = { id };
16
+ const slug = Slugger.slug(data.headline);
17
+ attr.id = slug || id;
18
+ const LinkedHeadline = useMemo(() => renderLinkElement(headlineTag), [
19
+ headlineTag,
20
+ ]);
21
+ return (
22
+ <LinkedHeadline
23
+ mode={!isEditMode && 'view'}
24
+ children={data.headline}
25
+ attributes={attr}
26
+ className={cx('headline', {
27
+ emptyListing: !listingItems?.length > 0,
28
+ })}
29
+ />
30
+ );
31
+ };
32
+
12
33
  const ListingBody = withQuerystringResults((props) => {
13
34
  const {
14
35
  data = {},
@@ -22,6 +43,7 @@ const ListingBody = withQuerystringResults((props) => {
22
43
  nextBatch,
23
44
  isFolderContentsListing,
24
45
  hasLoaded,
46
+ id,
25
47
  } = props;
26
48
 
27
49
  let ListingBodyTemplate;
@@ -50,13 +72,13 @@ const ListingBody = withQuerystringResults((props) => {
50
72
  return (
51
73
  <>
52
74
  {data.headline && (
53
- <HeadlineTag
54
- className={cx('headline', {
55
- emptyListing: !listingItems?.length > 0,
56
- })}
57
- >
58
- {data.headline}
59
- </HeadlineTag>
75
+ <Headline
76
+ headlineTag={HeadlineTag}
77
+ id={id}
78
+ listingItems={listingItems}
79
+ data={data}
80
+ isEditMode={isEditMode}
81
+ />
60
82
  )}
61
83
  {listingItems?.length > 0 ? (
62
84
  <div ref={listingRef}>
@@ -36,6 +36,26 @@ test('renders a ListingBody component', () => {
36
36
  content: {
37
37
  data: {
38
38
  is_folderish: true,
39
+ blocks: {
40
+ '839ee00b-013b-4f4a-9b10-8867938fdac3': {
41
+ '@type': 'listing',
42
+ block: '839ee00b-013b-4f4a-9b10-8867938fdac3',
43
+ headlineTag: 'h2',
44
+ query: [],
45
+ querystring: {
46
+ b_size: '2',
47
+ query: [
48
+ {
49
+ i: 'path',
50
+ o: 'plone.app.querystring.operation.string.absolutePath',
51
+ v: '/',
52
+ },
53
+ ],
54
+ sort_order: 'ascending',
55
+ },
56
+ variation: 'default',
57
+ },
58
+ },
39
59
  },
40
60
  },
41
61
  intl: {
@@ -27,7 +27,7 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
27
27
  <ConditionalLink item={item} condition={!isEditMode}>
28
28
  <Component componentName="PreviewImage" item={item} alt="" />
29
29
  <div className="listing-body">
30
- <h3>{item.title ? item.title : item.id}</h3>
30
+ <h3>{item.title || item.id}</h3>
31
31
  <p>{item.description}</p>
32
32
  </div>
33
33
  </ConditionalLink>
@@ -1,7 +1,13 @@
1
1
  import { getQueryStringResults } from '@plone/volto/actions';
2
2
  import { resolveBlockExtensions } from '@plone/volto/helpers';
3
3
 
4
- export default ({ dispatch, data, path, blocksConfig }) => {
4
+ export default function getListingBlockAsyncData({
5
+ dispatch,
6
+ id,
7
+ data,
8
+ path,
9
+ blocksConfig,
10
+ }) {
5
11
  const { resolvedExtensions } = resolveBlockExtensions(data, blocksConfig);
6
12
 
7
13
  return [
@@ -14,8 +20,8 @@ export default ({ dispatch, data, path, blocksConfig }) => {
14
20
  ? { fullobjects: 1 }
15
21
  : { metadata_fields: '_all' }),
16
22
  },
17
- data.block,
23
+ id,
18
24
  ),
19
25
  ),
20
26
  ];
21
- };
27
+ }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useRef } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import hoistNonReactStatics from 'hoist-non-react-statics';
4
4
  import useDeepCompareEffect from 'use-deep-compare-effect';
@@ -14,18 +14,23 @@ function getDisplayName(WrappedComponent) {
14
14
 
15
15
  export default function withQuerystringResults(WrappedComponent) {
16
16
  function WithQuerystringResults(props) {
17
- const { data = {}, properties: content, path, variation } = props;
17
+ const {
18
+ data = {},
19
+ id = data.block,
20
+ properties: content,
21
+ path,
22
+ variation,
23
+ } = props;
18
24
  const { settings } = config;
19
25
  const querystring = data.querystring || data; // For backwards compat with data saved before Blocks schema. Note, this is also how the Search block passes data to ListingBody
20
26
 
21
- const { block } = data;
22
27
  const { b_size = settings.defaultPageSize } = querystring; // batchsize
23
28
 
24
29
  // save the path so it won't trigger dispatch on eager router location change
25
30
  const [initialPath] = React.useState(getBaseUrl(path));
26
31
 
27
32
  const copyFields = ['limit', 'query', 'sort_on', 'sort_order', 'depth'];
28
-
33
+ const { currentPage, setCurrentPage } = usePagination(id, 1);
29
34
  const adaptedQuery = Object.assign(
30
35
  variation?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' },
31
36
  {
@@ -37,7 +42,9 @@ export default function withQuerystringResults(WrappedComponent) {
37
42
  : {},
38
43
  ),
39
44
  );
40
- const { currentPage, setCurrentPage } = usePagination(querystring, 1);
45
+ const adaptedQueryRef = useRef(adaptedQuery);
46
+ const currentPageRef = useRef(currentPage);
47
+
41
48
  const querystringResults = useSelector(
42
49
  (state) => state.querystringsearch.subrequests,
43
50
  );
@@ -45,32 +52,31 @@ export default function withQuerystringResults(WrappedComponent) {
45
52
 
46
53
  const folderItems = content?.is_folderish ? content.items : [];
47
54
  const hasQuery = querystring?.query?.length > 0;
48
- const hasLoaded = hasQuery ? !querystringResults?.[block]?.loading : true;
55
+ const hasLoaded = hasQuery ? querystringResults?.[id]?.loaded : true;
49
56
 
50
- const listingItems =
51
- querystring?.query?.length > 0 && querystringResults?.[block]
52
- ? querystringResults?.[block]?.items || []
53
- : folderItems;
57
+ const listingItems = hasQuery
58
+ ? querystringResults?.[id]?.items || []
59
+ : folderItems;
54
60
 
55
61
  const showAsFolderListing = !hasQuery && content?.items_total > b_size;
56
62
  const showAsQueryListing =
57
- hasQuery && querystringResults?.[block]?.total > b_size;
63
+ hasQuery && querystringResults?.[id]?.total > b_size;
58
64
 
59
65
  const totalPages = showAsFolderListing
60
66
  ? Math.ceil(content.items_total / b_size)
61
67
  : showAsQueryListing
62
- ? Math.ceil(querystringResults[block].total / b_size)
68
+ ? Math.ceil(querystringResults[id].total / b_size)
63
69
  : 0;
64
70
 
65
71
  const prevBatch = showAsFolderListing
66
72
  ? content.batching?.prev
67
73
  : showAsQueryListing
68
- ? querystringResults[block].batching?.prev
74
+ ? querystringResults[id].batching?.prev
69
75
  : null;
70
76
  const nextBatch = showAsFolderListing
71
77
  ? content.batching?.next
72
78
  : showAsQueryListing
73
- ? querystringResults[block].batching?.next
79
+ ? querystringResults[id].batching?.next
74
80
  : null;
75
81
 
76
82
  const isImageGallery =
@@ -80,7 +86,7 @@ export default function withQuerystringResults(WrappedComponent) {
80
86
  useDeepCompareEffect(() => {
81
87
  if (hasQuery) {
82
88
  dispatch(
83
- getQueryStringResults(initialPath, adaptedQuery, block, currentPage),
89
+ getQueryStringResults(initialPath, adaptedQuery, id, currentPage),
84
90
  );
85
91
  } else if (isImageGallery && !hasQuery) {
86
92
  // when used as image gallery, it doesn't need a query to list children
@@ -98,14 +104,16 @@ export default function withQuerystringResults(WrappedComponent) {
98
104
  },
99
105
  ],
100
106
  },
101
- block,
107
+ id,
102
108
  ),
103
109
  );
104
110
  } else {
105
111
  dispatch(getContent(initialPath, null, null, currentPage));
106
112
  }
113
+ adaptedQueryRef.current = adaptedQuery;
114
+ currentPageRef.current = currentPage;
107
115
  }, [
108
- block,
116
+ id,
109
117
  isImageGallery,
110
118
  adaptedQuery,
111
119
  hasQuery,
@@ -118,7 +126,7 @@ export default function withQuerystringResults(WrappedComponent) {
118
126
  <WrappedComponent
119
127
  {...props}
120
128
  onPaginationChange={(e, { activePage }) => setCurrentPage(activePage)}
121
- total={querystringResults?.[block]?.total}
129
+ total={querystringResults?.[id]?.total}
122
130
  batch_size={b_size}
123
131
  currentPage={currentPage}
124
132
  totalPages={totalPages}
@@ -1,5 +1,4 @@
1
- import React from 'react';
2
- import useDeepCompareEffect from 'use-deep-compare-effect';
1
+ import React, { useEffect } from 'react';
3
2
  import { defineMessages } from 'react-intl';
4
3
  import { compose } from 'redux';
5
4
 
@@ -60,9 +59,11 @@ const SearchBlockEdit = (props) => {
60
59
  };
61
60
 
62
61
  const { query = {} } = data || {};
63
- useDeepCompareEffect(() => {
62
+ // We don't need deep compare here, as this is just json serializable data.
63
+ const deepQuery = JSON.stringify(query);
64
+ useEffect(() => {
64
65
  onTriggerSearch();
65
- }, [query, onTriggerSearch]);
66
+ }, [deepQuery, onTriggerSearch]);
66
67
 
67
68
  return (
68
69
  <>
@@ -57,7 +57,7 @@ const applyDefaults = (data, root) => {
57
57
  };
58
58
 
59
59
  const SearchBlockView = (props) => {
60
- const { data, searchData, mode = 'view', variation } = props;
60
+ const { id, data, searchData, mode = 'view', variation } = props;
61
61
 
62
62
  const Layout = variation.view;
63
63
 
@@ -89,6 +89,7 @@ const SearchBlockView = (props) => {
89
89
  setSelectedView={setSelectedView}
90
90
  >
91
91
  <ListingBody
92
+ id={id}
92
93
  variation={{ ...data, ...listingBodyVariation }}
93
94
  data={listingBodyData}
94
95
  path={props.path}
@@ -4,6 +4,7 @@ import { defineMessages, injectIntl } from 'react-intl';
4
4
  import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
5
5
  import { compose } from 'redux';
6
6
  import { Icon } from '@plone/volto/components';
7
+ import { toBackendLang } from '@plone/volto/helpers/Utils/Utils';
7
8
  import { connect } from 'react-redux';
8
9
 
9
10
  import leftKey from '@plone/volto/icons/left-key.svg';
@@ -82,7 +83,9 @@ const DateRangeFacet = (props) => {
82
83
  noBorder
83
84
  showClearDates
84
85
  customCloseIcon={<CloseIcon />}
85
- displayFormat={moment.localeData(lang).longDateFormat('L')}
86
+ displayFormat={moment
87
+ .localeData(toBackendLang(lang))
88
+ .longDateFormat('L')}
86
89
  focusedInput={focused}
87
90
  onFocusChange={(focusedInput) => setFocused(focusedInput)}
88
91
  onDatesChange={({ startDate, endDate }) => {