@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
@@ -0,0 +1,14 @@
1
+ export const GridBlockDataAdapter = ({
2
+ block,
3
+ data,
4
+ id,
5
+ onChangeBlock,
6
+ value,
7
+ }) => {
8
+ let dataSaved = {
9
+ ...data,
10
+ [id]: value,
11
+ };
12
+
13
+ onChangeBlock(block, dataSaved);
14
+ };
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <rect width="67" height="53" fill="#FFF" opacity=".9" transform="translate(15 22)"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,9 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <g fill="#FFF" opacity=".9" transform="translate(9 22)">
5
+ <rect width="37" height="53"/>
6
+ <rect width="37" height="53" x="42"/>
7
+ </g>
8
+ </g>
9
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <g fill="#FFF" opacity=".9" transform="translate(6 22)">
5
+ <rect width="25" height="53" x="58"/>
6
+ <rect width="25" height="53"/>
7
+ <rect width="25" height="53" x="29"/>
8
+ </g>
9
+ </g>
10
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <g fill="#FFF" opacity=".9" transform="translate(8 22)">
5
+ <rect width="18" height="53" x="42"/>
6
+ <rect width="18" height="53" x="63"/>
7
+ <rect width="18" height="53"/>
8
+ <rect width="18" height="53" x="21"/>
9
+ </g>
10
+ </g>
11
+ </svg>
@@ -0,0 +1,35 @@
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ const messages = defineMessages({
4
+ headline: {
5
+ id: 'Headline',
6
+ defaultMessage: 'Headline',
7
+ },
8
+ grid: {
9
+ id: 'Grid',
10
+ defaultMessage: 'Grid',
11
+ },
12
+ });
13
+
14
+ export const GridBlockSchema = (props) => {
15
+ const { intl } = props;
16
+
17
+ return {
18
+ title: intl.formatMessage(messages.grid),
19
+ block: 'grid',
20
+ fieldsets: [
21
+ {
22
+ id: 'default',
23
+ title: 'Default',
24
+ fields: ['headline'],
25
+ },
26
+ ],
27
+
28
+ properties: {
29
+ headline: {
30
+ title: intl.formatMessage(messages.headline),
31
+ },
32
+ },
33
+ required: [],
34
+ };
35
+ };
@@ -0,0 +1,47 @@
1
+ import { defineMessages } from 'react-intl';
2
+ import { blocksFormGenerator } from '@plone/volto/helpers';
3
+
4
+ import gridTemplate1 from './grid-1.svg';
5
+ import gridTemplate2 from './grid-2.svg';
6
+ import gridTemplate3 from './grid-3.svg';
7
+ import gridTemplate4 from './grid-4.svg';
8
+
9
+ const messages = defineMessages({
10
+ column: {
11
+ id: 'column',
12
+ defaultMessage: 'column',
13
+ },
14
+ columns: {
15
+ id: 'columns',
16
+ defaultMessage: 'columns',
17
+ },
18
+ });
19
+
20
+ const templates = (type) => (intl) => [
21
+ {
22
+ image: gridTemplate1,
23
+ id: 'gridtemplateone',
24
+ title: `1 ${intl.formatMessage(messages.column)}`,
25
+ blocksData: blocksFormGenerator(1, type),
26
+ },
27
+ {
28
+ image: gridTemplate2,
29
+ id: 'gridtemplatetwo',
30
+ title: `2 ${intl.formatMessage(messages.columns)}`,
31
+ blocksData: blocksFormGenerator(2, type),
32
+ },
33
+ {
34
+ image: gridTemplate3,
35
+ id: 'gridtemplatethree',
36
+ title: `3 ${intl.formatMessage(messages.columns)}`,
37
+ blocksData: blocksFormGenerator(3, type),
38
+ },
39
+ {
40
+ image: gridTemplate4,
41
+ id: 'gridtemplatefour',
42
+ title: `4 ${intl.formatMessage(messages.columns)}`,
43
+ blocksData: blocksFormGenerator(4, type),
44
+ },
45
+ ];
46
+
47
+ export default templates;
@@ -14,7 +14,11 @@ import { defineMessages, injectIntl } from 'react-intl';
14
14
  import cx from 'classnames';
15
15
 
16
16
  import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
17
- import { flattenToAppURL, getBaseUrl } from '@plone/volto/helpers';
17
+ import {
18
+ flattenToAppURL,
19
+ getBaseUrl,
20
+ validateFileUploadSize,
21
+ } from '@plone/volto/helpers';
18
22
  import { createContent } from '@plone/volto/actions';
19
23
  import { Icon, SidebarPortal, LinkMore } from '@plone/volto/components';
20
24
 
@@ -275,6 +279,7 @@ class EditComponent extends Component {
275
279
  */
276
280
  onUploadImage({ target }) {
277
281
  const file = target.files[0];
282
+ if (!validateFileUploadSize(file, this.props.intl.formatMessage)) return;
278
283
  this.setState({
279
284
  uploading: true,
280
285
  });
@@ -15,13 +15,15 @@ import cx from 'classnames';
15
15
  import { isEqual } from 'lodash';
16
16
 
17
17
  import { Icon, ImageSidebar, SidebarPortal } from '@plone/volto/components';
18
- import { withBlockExtensions } from '@plone/volto/helpers';
19
18
  import { createContent } from '@plone/volto/actions';
20
19
  import {
21
20
  flattenToAppURL,
22
21
  getBaseUrl,
23
22
  isInternalURL,
23
+ withBlockExtensions,
24
+ validateFileUploadSize,
24
25
  } from '@plone/volto/helpers';
26
+ import config from '@plone/volto/registry';
25
27
 
26
28
  import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
27
29
  import clearSVG from '@plone/volto/icons/clear.svg';
@@ -58,7 +60,7 @@ class Edit extends Component {
58
60
  block: PropTypes.string.isRequired,
59
61
  index: PropTypes.number.isRequired,
60
62
  data: PropTypes.objectOf(PropTypes.any).isRequired,
61
- content: PropTypes.objectOf(PropTypes.any).isRequired,
63
+ content: PropTypes.objectOf(PropTypes.any),
62
64
  request: PropTypes.shape({
63
65
  loading: PropTypes.bool,
64
66
  loaded: PropTypes.bool,
@@ -87,6 +89,7 @@ class Edit extends Component {
87
89
  * @returns {undefined}
88
90
  */
89
91
  UNSAFE_componentWillReceiveProps(nextProps) {
92
+ // Update block data after upload finished
90
93
  if (
91
94
  this.props.request.loading &&
92
95
  nextProps.request.loaded &&
@@ -98,6 +101,8 @@ class Edit extends Component {
98
101
  this.props.onChangeBlock(this.props.block, {
99
102
  ...this.props.data,
100
103
  url: nextProps.content['@id'],
104
+ image_field: 'image',
105
+ image_scales: { image: [nextProps.content.image] },
101
106
  alt: '',
102
107
  });
103
108
  }
@@ -125,6 +130,7 @@ class Edit extends Component {
125
130
  onUploadImage = (e) => {
126
131
  e.stopPropagation();
127
132
  const file = e.target.files[0];
133
+ if (!validateFileUploadSize(file, this.props.intl.formatMessage)) return;
128
134
  this.setState({
129
135
  uploading: true,
130
136
  });
@@ -169,6 +175,8 @@ class Edit extends Component {
169
175
  this.props.onChangeBlock(this.props.block, {
170
176
  ...this.props.data,
171
177
  url: flattenToAppURL(this.state.url),
178
+ image_field: undefined,
179
+ image_scales: undefined,
172
180
  });
173
181
  };
174
182
 
@@ -178,23 +186,25 @@ class Edit extends Component {
178
186
  * @param {array} files File objects
179
187
  * @returns {undefined}
180
188
  */
181
- onDrop = (file) => {
182
- this.setState({
183
- uploading: true,
184
- });
189
+ onDrop = (files) => {
190
+ if (!validateFileUploadSize(files[0], this.props.intl.formatMessage)) {
191
+ this.setState({ dragging: false });
192
+ return;
193
+ }
194
+ this.setState({ uploading: true });
185
195
 
186
- readAsDataURL(file[0]).then((data) => {
196
+ readAsDataURL(files[0]).then((data) => {
187
197
  const fields = data.match(/^data:(.*);(.*),(.*)$/);
188
198
  this.props.createContent(
189
199
  getBaseUrl(this.props.pathname),
190
200
  {
191
201
  '@type': 'Image',
192
- title: file[0].name,
202
+ title: files[0].name,
193
203
  image: {
194
204
  data: fields[3],
195
205
  encoding: fields[2],
196
206
  'content-type': fields[1],
197
- filename: file[0].name,
207
+ filename: files[0].name,
198
208
  },
199
209
  },
200
210
  this.props.block,
@@ -236,10 +246,12 @@ class Edit extends Component {
236
246
  * @returns {string} Markup for the component.
237
247
  */
238
248
  render() {
249
+ const Image = config.getComponent({ name: 'Image' }).component;
239
250
  const { data } = this.props;
240
251
  const placeholder =
241
252
  this.props.data.placeholder ||
242
253
  this.props.intl.formatMessage(messages.ImageBlockInputPlaceholder);
254
+
243
255
  return (
244
256
  <div
245
257
  className={cx(
@@ -251,15 +263,26 @@ class Edit extends Component {
251
263
  )}
252
264
  >
253
265
  {data.url ? (
254
- <img
266
+ <Image
255
267
  className={cx({
256
268
  'full-width': data.align === 'full',
257
269
  large: data.size === 'l',
258
270
  medium: data.size === 'm',
259
271
  small: data.size === 's',
260
272
  })}
273
+ item={
274
+ data.image_scales
275
+ ? {
276
+ '@id': data.url,
277
+ image_field: data.image_field,
278
+ image_scales: data.image_scales,
279
+ }
280
+ : undefined
281
+ }
261
282
  src={
262
- isInternalURL(data.url)
283
+ data.image_scales
284
+ ? undefined
285
+ : isInternalURL(data.url)
263
286
  ? // Backwards compat in the case that the block is storing the full server URL
264
287
  (() => {
265
288
  if (data.size === 'l')
@@ -274,7 +297,10 @@ class Edit extends Component {
274
297
  })()
275
298
  : data.url
276
299
  }
300
+ sizes={config.blocks.blocksConfig.image.getSizes(data)}
277
301
  alt={data.alt || ''}
302
+ loading="lazy"
303
+ responsive={true}
278
304
  />
279
305
  ) : (
280
306
  <div>
@@ -309,7 +335,20 @@ class Edit extends Component {
309
335
  onClick={(e) => {
310
336
  e.stopPropagation();
311
337
  e.preventDefault();
312
- this.props.openObjectBrowser();
338
+ this.props.openObjectBrowser({
339
+ onSelectItem: (
340
+ url,
341
+ { title, image_field, image_scales },
342
+ ) => {
343
+ this.props.onChangeBlock(this.props.block, {
344
+ ...this.props.data,
345
+ url,
346
+ image_field,
347
+ image_scales,
348
+ alt: this.props.data.alt || title || '',
349
+ });
350
+ },
351
+ });
313
352
  }}
314
353
  >
315
354
  <Icon name={navTreeSVG} size="24px" />
@@ -3,6 +3,7 @@ import renderer from 'react-test-renderer';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import { waitFor } from '@testing-library/react';
6
+ import { getImageBlockSizes } from './utils';
6
7
  import config from '@plone/volto/registry';
7
8
 
8
9
  import Edit from './Edit';
@@ -25,6 +26,7 @@ config.blocks.blocksConfig = {
25
26
  addPermission: [],
26
27
  view: [],
27
28
  },
29
+ getSizes: getImageBlockSizes,
28
30
  },
29
31
  };
30
32
 
@@ -1,14 +1,15 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Segment } from 'semantic-ui-react';
4
- import { useIntl, FormattedMessage } from 'react-intl';
5
- import { BlockDataForm, Icon } from '@plone/volto/components';
6
- import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers';
3
+ import { Segment, Button } from 'semantic-ui-react';
4
+ import { useIntl, FormattedMessage, defineMessages } from 'react-intl';
5
+ import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers';
6
+ import { BlockDataForm, Icon, Image } from '@plone/volto/components';
7
7
  import { ImageSchema } from './schema';
8
8
  import imageSVG from '@plone/volto/icons/image.svg';
9
+ import trashSVG from '@plone/volto/icons/delete.svg';
9
10
 
10
11
  const ImageSidebar = (props) => {
11
- const { data, block, onChangeBlock } = props;
12
+ const { blocksConfig, data, block, onChangeBlock } = props;
12
13
  const intl = useIntl();
13
14
  const schema = ImageSchema({ formData: data, intl });
14
15
  return (
@@ -17,21 +18,58 @@ const ImageSidebar = (props) => {
17
18
  <h2>
18
19
  <FormattedMessage id="Image" defaultMessage="Image" />
19
20
  </h2>
21
+ <Button.Group>
22
+ <Button
23
+ title={intl.formatMessage(messages.clear)}
24
+ basic
25
+ disabled={!data.url}
26
+ onClick={() => {
27
+ onChangeBlock(block, {
28
+ ...data,
29
+ url: undefined,
30
+ image_scales: undefined,
31
+ image_field: undefined,
32
+ alt: data.url.title === data.alt ? undefined : data.alt,
33
+ });
34
+ }}
35
+ >
36
+ <Icon name={trashSVG} size="24px" color="red" />
37
+ </Button>
38
+ </Button.Group>
20
39
  </header>
21
40
 
22
- <Segment className="sidebar-metadata-container" secondary attached>
41
+ <Segment
42
+ className="sidebar-metadata-container image-sidebar"
43
+ secondary
44
+ attached
45
+ >
23
46
  {data.url ? (
24
47
  <>
25
- {data.url.split('/').slice(-1)[0]}
26
- {isInternalURL(data.url) && (
27
- <img
28
- src={`${flattenToAppURL(data.url)}/@@images/image/mini`}
29
- alt={data.alt}
30
- />
31
- )}
32
- {!isInternalURL(data.url) && (
33
- <img src={data.url} alt={data.alt} style={{ width: '50%' }} />
34
- )}
48
+ <div>{(data.url?.['@id'] ?? data.url).split('/').slice(-1)[0]}</div>
49
+ <Image
50
+ item={
51
+ data.image_scales
52
+ ? {
53
+ '@id': data.url,
54
+ image_field: data.image_field,
55
+ image_scales: data.image_scales,
56
+ }
57
+ : undefined
58
+ }
59
+ src={
60
+ data.image_scales
61
+ ? undefined
62
+ : isInternalURL(data.url)
63
+ ? // Backwards compat in the case that the block is storing the full server URL
64
+ `${flattenToAppURL(data.url)}/@@images/image/preview`
65
+ : data.url
66
+ }
67
+ sizes="188px"
68
+ alt={intl.formatMessage(messages.preview)}
69
+ loading="lazy"
70
+ responsive={true}
71
+ style={{ width: '50%' }}
72
+ />
35
73
  </>
36
74
  ) : (
37
75
  <>
@@ -55,6 +93,7 @@ const ImageSidebar = (props) => {
55
93
  onChangeBlock={onChangeBlock}
56
94
  formData={data}
57
95
  block={block}
96
+ blocksConfig={blocksConfig}
58
97
  />
59
98
  </>
60
99
  );
@@ -67,3 +106,14 @@ ImageSidebar.propTypes = {
67
106
  };
68
107
 
69
108
  export default ImageSidebar;
109
+
110
+ const messages = defineMessages({
111
+ preview: {
112
+ id: 'image_block_preview',
113
+ defaultMessage: 'Image preview',
114
+ },
115
+ clear: {
116
+ id: 'image_block_clear',
117
+ defaultMessage: 'Clear image',
118
+ },
119
+ });
@@ -7,16 +7,23 @@ 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
- import { withBlockExtensions } from '@plone/volto/helpers';
11
- import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers';
10
+ import {
11
+ flattenToAppURL,
12
+ isInternalURL,
13
+ withBlockExtensions,
14
+ } from '@plone/volto/helpers';
15
+ import config from '@plone/volto/registry';
12
16
 
13
17
  /**
14
18
  * View image block class.
15
19
  * @class View
16
20
  * @extends Component
17
21
  */
18
- export const View = ({ data, detached }) => {
22
+ export const View = ({ data, detached, properties }) => {
19
23
  const href = data?.href?.[0]?.['@id'] || '';
24
+
25
+ const Image = config.getComponent({ name: 'Image' }).component;
26
+
20
27
  return (
21
28
  <p
22
29
  className={cx(
@@ -32,15 +39,26 @@ export const View = ({ data, detached }) => {
32
39
  <>
33
40
  {(() => {
34
41
  const image = (
35
- <img
42
+ <Image
36
43
  className={cx({
37
44
  'full-width': data.align === 'full',
38
45
  large: data.size === 'l',
39
46
  medium: data.size === 'm',
40
47
  small: data.size === 's',
41
48
  })}
49
+ item={
50
+ data.image_scales
51
+ ? {
52
+ '@id': data.url,
53
+ image_field: data.image_field,
54
+ image_scales: data.image_scales,
55
+ }
56
+ : undefined
57
+ }
42
58
  src={
43
- isInternalURL(data.url)
59
+ data.image_scales
60
+ ? undefined
61
+ : isInternalURL(data.url)
44
62
  ? // Backwards compat in the case that the block is storing the full server URL
45
63
  (() => {
46
64
  if (data.size === 'l')
@@ -57,8 +75,10 @@ export const View = ({ data, detached }) => {
57
75
  })()
58
76
  : data.url
59
77
  }
78
+ sizes={config.blocks.blocksConfig.image.getSizes(data)}
60
79
  alt={data.alt || ''}
61
80
  loading="lazy"
81
+ responsive={true}
62
82
  />
63
83
  );
64
84
  if (href) {
@@ -4,6 +4,8 @@ import { render } from '@testing-library/react';
4
4
  import { MemoryRouter } from 'react-router-dom';
5
5
  import { Provider } from 'react-intl-redux';
6
6
  import configureStore from 'redux-mock-store';
7
+ import { getImageBlockSizes } from './utils';
8
+ import config from '@plone/volto/registry';
7
9
  import { View } from './View';
8
10
 
9
11
  const mockStore = configureStore();
@@ -15,6 +17,24 @@ const store = mockStore({
15
17
  },
16
18
  });
17
19
 
20
+ config.blocks.blocksConfig = {
21
+ image: {
22
+ id: 'image',
23
+ title: 'Image',
24
+ group: 'media',
25
+ extensions: {},
26
+ variations: [],
27
+ restricted: false,
28
+ mostUsed: true,
29
+ sidebarTab: 1,
30
+ security: {
31
+ addPermission: [],
32
+ view: [],
33
+ },
34
+ getSizes: getImageBlockSizes,
35
+ },
36
+ };
37
+
18
38
  describe('Image View Component', () => {
19
39
  test('renders a view image component with a local image', () => {
20
40
  const { getByRole } = render(<View data={{ url: '/image.jpg' }} />);
@@ -1,10 +1,6 @@
1
1
  import { defineMessages } from 'react-intl';
2
2
 
3
3
  const messages = defineMessages({
4
- Source: {
5
- id: 'Source',
6
- defaultMessage: 'Source',
7
- },
8
4
  Image: {
9
5
  id: 'Image',
10
6
  defaultMessage: 'Image',
@@ -45,7 +41,7 @@ export function ImageSchema({ formData, intl }) {
45
41
  {
46
42
  id: 'default',
47
43
  title: 'Default',
48
- fields: [...(formData.url ? ['url', 'alt', 'align', 'size'] : [])],
44
+ fields: [...(formData.url ? ['alt', 'align', 'size'] : [])],
49
45
  },
50
46
  ...(formData.url
51
47
  ? [
@@ -58,10 +54,6 @@ export function ImageSchema({ formData, intl }) {
58
54
  : []),
59
55
  ],
60
56
  properties: {
61
- url: {
62
- title: intl.formatMessage(messages.Source),
63
- widget: 'url',
64
- },
65
57
  alt: {
66
58
  title: intl.formatMessage(messages.AltText),
67
59
  description: (
@@ -101,3 +93,14 @@ export function ImageSchema({ formData, intl }) {
101
93
  required: [],
102
94
  };
103
95
  }
96
+
97
+ export const gridImageDisableSizeAndPositionHandlersSchema = ({
98
+ schema,
99
+ formData,
100
+ intl,
101
+ }) => {
102
+ schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter(
103
+ (item) => !['align', 'size'].includes(item),
104
+ );
105
+ return schema;
106
+ };
@@ -0,0 +1,14 @@
1
+ export function getImageBlockSizes(data) {
2
+ if (data.align === 'full') return '100vw';
3
+ if (data.align === 'center') {
4
+ if (data.size === 'l') return '100vw';
5
+ if (data.size === 'm') return '50vw';
6
+ if (data.size === 's') return '25vw';
7
+ }
8
+ if (data.align === 'left' || data.align === 'right') {
9
+ if (data.size === 'l') return '50vw';
10
+ if (data.size === 'm') return '25vw';
11
+ if (data.size === 's') return '15vw';
12
+ }
13
+ return undefined;
14
+ }