@plone/volto 17.0.0-alpha.9 → 17.0.1

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 (365) hide show
  1. package/.eslintrc +26 -3
  2. package/CHANGELOG.md +774 -5
  3. package/CONTRIBUTING.md +5 -1
  4. package/README.md +12 -9
  5. package/RELEASING.md +5 -5
  6. package/addon-registry.js +10 -1
  7. package/create-addons-loader.js +1 -1
  8. package/cypress/support/commands.js +70 -14
  9. package/cypress/support/e2e.js +1 -2
  10. package/cypress/support/volto-slate.js +4 -5
  11. package/cypress.config.js +1 -0
  12. package/docker-compose.yml +1 -1
  13. package/locales/ca/LC_MESSAGES/volto.po +281 -53
  14. package/locales/ca.json +1 -1
  15. package/locales/de/LC_MESSAGES/volto.po +289 -61
  16. package/locales/de.json +1 -1
  17. package/locales/en/LC_MESSAGES/volto.po +279 -51
  18. package/locales/en.json +1 -1
  19. package/locales/es/LC_MESSAGES/volto.po +318 -90
  20. package/locales/es.json +1 -1
  21. package/locales/eu/LC_MESSAGES/volto.po +280 -52
  22. package/locales/eu.json +1 -1
  23. package/locales/fi/LC_MESSAGES/volto.po +280 -52
  24. package/locales/fi.json +1 -1
  25. package/locales/fr/LC_MESSAGES/volto.po +281 -53
  26. package/locales/fr.json +1 -1
  27. package/locales/it/LC_MESSAGES/volto.po +474 -246
  28. package/locales/it.json +1 -1
  29. package/locales/ja/LC_MESSAGES/volto.po +280 -52
  30. package/locales/ja.json +1 -1
  31. package/locales/nl/LC_MESSAGES/volto.po +281 -53
  32. package/locales/nl.json +1 -1
  33. package/locales/pt/LC_MESSAGES/volto.po +281 -53
  34. package/locales/pt.json +1 -1
  35. package/locales/pt_BR/LC_MESSAGES/volto.po +314 -86
  36. package/locales/pt_BR.json +1 -1
  37. package/locales/ro/LC_MESSAGES/volto.po +281 -53
  38. package/locales/ro.json +1 -1
  39. package/locales/volto.pot +284 -52
  40. package/locales/zh_CN/LC_MESSAGES/volto.po +281 -53
  41. package/locales/zh_CN.json +1 -1
  42. package/package.json +44 -34
  43. package/packages/volto-slate/package.json +1 -1
  44. package/packages/volto-slate/src/actions/index.js +1 -1
  45. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.jsx +21 -212
  46. package/packages/volto-slate/src/blocks/Table/schema.js +122 -0
  47. package/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx +8 -3
  48. package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +21 -16
  49. package/packages/volto-slate/src/blocks/Text/extensions/withDeserializers.js +3 -1
  50. package/packages/volto-slate/src/blocks/Text/index.js +10 -7
  51. package/packages/volto-slate/src/editor/config.jsx +5 -4
  52. package/packages/volto-slate/src/editor/index.js +4 -4
  53. package/packages/volto-slate/src/editor/less/slate.less +28 -0
  54. package/packages/volto-slate/src/editor/plugins/Link/render.jsx +5 -6
  55. package/packages/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx +14 -4
  56. package/packages/volto-slate/src/editor/plugins/StyleMenu/utils.js +14 -5
  57. package/packages/volto-slate/src/editor/render.jsx +77 -8
  58. package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +2 -2
  59. package/packages/volto-slate/src/editor/ui/index.js +15 -15
  60. package/packages/volto-slate/src/index.js +2 -2
  61. package/packages/volto-slate/src/utils/blocks.js +7 -0
  62. package/packages/volto-slate/src/widgets/RichTextWidget.jsx +15 -8
  63. package/razzle.config.js +4 -6
  64. package/src/actions/index.js +4 -0
  65. package/src/actions/navroot/navroot.js +16 -0
  66. package/src/actions/navroot/navroot.test.js +15 -0
  67. package/src/actions/relations/rebuild.js +7 -7
  68. package/src/actions/relations/relations.js +17 -0
  69. package/src/actions/site/site.js +16 -0
  70. package/src/actions/site/site.test.js +15 -0
  71. package/src/actions/userSession/userSession.js +17 -1
  72. package/src/components/index.js +194 -192
  73. package/src/components/manage/Actions/Actions.jsx +133 -243
  74. package/src/components/manage/Add/Add.jsx +7 -8
  75. package/src/components/manage/AnchorPlugin/index.jsx +2 -2
  76. package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +3 -1
  77. package/src/components/manage/Blocks/Block/BlocksForm.jsx +19 -2
  78. package/src/components/manage/Blocks/Block/Edit.jsx +1 -1
  79. package/src/components/manage/Blocks/Block/Settings.jsx +2 -0
  80. package/src/components/manage/Blocks/Block/Settings.test.jsx +92 -0
  81. package/src/components/manage/Blocks/Block/Style.jsx +2 -2
  82. package/src/components/manage/Blocks/Container/Data.jsx +32 -0
  83. package/src/components/manage/Blocks/Container/Edit.jsx +177 -0
  84. package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +121 -0
  85. package/src/components/manage/Blocks/Container/NewBlockAddButton.jsx +84 -0
  86. package/src/components/manage/Blocks/Container/SimpleContainerToolbar.jsx +54 -0
  87. package/src/components/manage/Blocks/Grid/Edit.jsx +47 -0
  88. package/src/components/manage/Blocks/Grid/View.jsx +43 -0
  89. package/src/components/manage/Blocks/Grid/adapter.js +14 -0
  90. package/src/components/manage/Blocks/Grid/grid-1.svg +6 -0
  91. package/src/components/manage/Blocks/Grid/grid-2.svg +9 -0
  92. package/src/components/manage/Blocks/Grid/grid-3.svg +10 -0
  93. package/src/components/manage/Blocks/Grid/grid-4.svg +11 -0
  94. package/src/components/manage/Blocks/Grid/schema.js +35 -0
  95. package/src/components/manage/Blocks/Grid/templates.js +47 -0
  96. package/src/components/manage/Blocks/HTML/Edit.jsx +8 -8
  97. package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +36 -26
  98. package/src/components/manage/Blocks/Image/Edit.jsx +51 -12
  99. package/src/components/manage/Blocks/Image/Edit.test.jsx +2 -0
  100. package/src/components/manage/Blocks/Image/ImageSidebar.jsx +66 -16
  101. package/src/components/manage/Blocks/Image/View.jsx +26 -5
  102. package/src/components/manage/Blocks/Image/View.test.jsx +20 -0
  103. package/src/components/manage/Blocks/Image/schema.js +17 -10
  104. package/src/components/manage/Blocks/Image/utils.js +14 -0
  105. package/src/components/manage/Blocks/LeadImage/Edit.jsx +32 -10
  106. package/src/components/manage/Blocks/LeadImage/Edit.test.jsx +11 -1
  107. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +28 -9
  108. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -2
  109. package/src/components/manage/Blocks/LeadImage/View.jsx +50 -38
  110. package/src/components/manage/Blocks/LeadImage/View.test.jsx +11 -1
  111. package/src/components/manage/Blocks/Listing/DefaultTemplate.jsx +18 -3
  112. package/src/components/manage/Blocks/Listing/ListingBody.jsx +32 -8
  113. package/src/components/manage/Blocks/Listing/ListingBody.test.jsx +20 -0
  114. package/src/components/manage/Blocks/Listing/SummaryTemplate.jsx +1 -1
  115. package/src/components/manage/Blocks/Listing/getAsyncData.js +3 -5
  116. package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +27 -17
  117. package/src/components/manage/Blocks/Maps/Edit.jsx +135 -209
  118. package/src/components/manage/Blocks/Maps/Edit.test.jsx +1 -2
  119. package/src/components/manage/Blocks/Maps/View.test.jsx +1 -2
  120. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +3 -2
  121. package/src/components/manage/Blocks/Search/components/Facets.jsx +66 -7
  122. package/src/components/manage/Blocks/Search/components/FilterList.jsx +4 -6
  123. package/src/components/manage/Blocks/Search/components/SearchInput.jsx +9 -2
  124. package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +2 -9
  125. package/src/components/manage/Blocks/Search/components/index.js +13 -13
  126. package/src/components/manage/Blocks/Search/hocs/index.js +2 -2
  127. package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +5 -2
  128. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +70 -36
  129. package/src/components/manage/Blocks/Search/layout/LeftColumnFacets.jsx +17 -5
  130. package/src/components/manage/Blocks/Search/layout/RightColumnFacets.jsx +17 -5
  131. package/src/components/manage/Blocks/Search/layout/TopSideFacets.jsx +21 -5
  132. package/src/components/manage/Blocks/Search/schema.js +29 -14
  133. package/src/components/manage/Blocks/Table/Cell.jsx +2 -3
  134. package/src/components/manage/Blocks/Teaser/Body.jsx +0 -1
  135. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +5 -10
  136. package/src/components/manage/Blocks/Teaser/schema.js +5 -0
  137. package/src/components/manage/Blocks/Text/Edit.jsx +2 -3
  138. package/src/components/manage/Blocks/Title/View.jsx +0 -23
  139. package/src/components/manage/Blocks/Title/View.test.jsx +16 -1
  140. package/src/components/manage/Blocks/ToC/Schema.jsx +40 -7
  141. package/src/components/manage/Blocks/ToC/View.jsx +84 -14
  142. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +8 -3
  143. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +44 -0
  144. package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +149 -10
  145. package/src/components/manage/Blocks/ToC/variations/index.js +3 -1
  146. package/src/components/manage/Blocks/Video/View.test.jsx +1 -1
  147. package/src/components/manage/Contents/Contents.jsx +285 -114
  148. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +90 -166
  149. package/src/components/manage/Contents/ContentsRenameModal.jsx +88 -139
  150. package/src/components/manage/Contents/ContentsRenameModal.stories.jsx +61 -0
  151. package/src/components/manage/Contents/ContentsTagsModal.jsx +83 -130
  152. package/src/components/manage/Contents/ContentsTagsModal.stories.jsx +68 -0
  153. package/src/components/manage/Contents/ContentsUploadModal.jsx +11 -7
  154. package/src/components/manage/Contents/ContentsWorkflowModal.jsx +87 -154
  155. package/src/components/manage/Controlpanels/Aliases.jsx +4 -12
  156. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +65 -38
  157. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +2 -2
  158. package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +38 -13
  159. package/src/components/manage/Controlpanels/Relations/Relations.jsx +5 -5
  160. package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +8 -7
  161. package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +68 -68
  162. package/src/components/manage/Controlpanels/Rules/AddRule.jsx +3 -10
  163. package/src/components/manage/Controlpanels/Rules/EditRule.jsx +1 -1
  164. package/src/components/manage/Controlpanels/UndoControlpanel.jsx +6 -9
  165. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +97 -7
  166. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +127 -99
  167. package/src/components/manage/Delete/Delete.jsx +96 -171
  168. package/src/components/manage/Diff/DiffField.jsx +25 -1
  169. package/src/components/manage/DragDropList/DragDropList.jsx +18 -13
  170. package/src/components/manage/Form/BlockDataForm.jsx +3 -2
  171. package/src/components/manage/Form/BlockDataForm.test.jsx +51 -17
  172. package/src/components/manage/Form/Form.jsx +7 -6
  173. package/src/components/manage/Form/InlineForm.test.jsx +16 -14
  174. package/src/components/manage/History/History.jsx +11 -1
  175. package/src/components/manage/LinksToItem/LinksToItem.jsx +209 -0
  176. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +100 -0
  177. package/src/components/manage/LockingToastsFactory/LockingToastsFactory.jsx +1 -2
  178. package/src/components/manage/Messages/Messages.jsx +32 -99
  179. package/src/components/manage/Messages/Messages.test.jsx +0 -1
  180. package/src/components/manage/Preferences/ChangePassword.jsx +2 -2
  181. package/src/components/manage/Sharing/Sharing.jsx +80 -22
  182. package/src/components/manage/Sidebar/AlignBlock.jsx +1 -1
  183. package/src/components/manage/Sidebar/Sidebar.jsx +139 -220
  184. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +38 -0
  185. package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +34 -0
  186. package/src/components/manage/TemplateChooser/template.svg +10 -0
  187. package/src/components/manage/Toast/Toast.jsx +1 -1
  188. package/src/components/manage/Toolbar/More.jsx +17 -2
  189. package/src/components/manage/Toolbar/PersonalTools.jsx +97 -155
  190. package/src/components/manage/Toolbar/Toolbar.jsx +2 -2
  191. package/src/components/manage/UniversalLink/UniversalLink.jsx +6 -12
  192. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +37 -0
  193. package/src/components/manage/Widgets/AlignWidget.jsx +2 -4
  194. package/src/components/manage/Widgets/ArrayWidget.jsx +3 -1
  195. package/src/components/manage/Widgets/ArrayWidget.test.jsx +45 -1
  196. package/src/components/manage/Widgets/ColorPickerWidget.jsx +6 -1
  197. package/src/components/manage/Widgets/ColorPickerWidget.test.jsx +9 -7
  198. package/src/components/manage/Widgets/DatetimeWidget.jsx +2 -8
  199. package/src/components/manage/Widgets/FileWidget.jsx +2 -1
  200. package/src/components/manage/Widgets/FormFieldWrapper.jsx +1 -1
  201. package/src/components/manage/Widgets/IdWidget.jsx +1 -2
  202. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +2 -9
  203. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +3 -10
  204. package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +4 -4
  205. package/src/components/manage/Widgets/RegistryImageWidget.jsx +210 -0
  206. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +91 -0
  207. package/src/components/manage/Widgets/SchemaWidget.jsx +6 -9
  208. package/src/components/manage/Widgets/SelectUtils.js +1 -1
  209. package/src/components/manage/Widgets/SelectWidget.jsx +15 -1
  210. package/src/components/manage/Widgets/SelectWidget.test.jsx +45 -1
  211. package/src/components/manage/Widgets/WysiwygWidget.jsx +2 -9
  212. package/src/components/manage/Workflow/Workflow.jsx +75 -184
  213. package/src/components/theme/Anontools/Anontools.jsx +44 -72
  214. package/src/components/theme/Anontools/Anontools.stories.jsx +16 -6
  215. package/src/components/theme/Anontools/Anontools.test.jsx +16 -2
  216. package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +52 -99
  217. package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.jsx +14 -13
  218. package/src/components/theme/Comments/Comment.stories.jsx +84 -0
  219. package/src/components/theme/Comments/CommentEditModal.jsx +63 -115
  220. package/src/components/theme/Comments/Comments.jsx +268 -380
  221. package/src/components/theme/Component/Component.jsx +1 -1
  222. package/src/components/theme/ContactForm/ContactForm.jsx +108 -192
  223. package/src/components/theme/ContactForm/ContactForm.stories.jsx +1 -1
  224. package/src/components/theme/ContactForm/ContactForm.test.jsx +2 -3
  225. package/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +41 -3
  226. package/src/components/theme/Error/ServerError.jsx +29 -0
  227. package/src/components/theme/Header/Header.jsx +37 -63
  228. package/src/components/theme/Header/Header.test.jsx +18 -0
  229. package/src/components/theme/Image/Image.jsx +96 -0
  230. package/src/components/theme/Image/Image.test.jsx +125 -0
  231. package/src/components/theme/Login/Login.jsx +160 -243
  232. package/src/components/theme/Logo/Logo.Multilingual.test.jsx +131 -1
  233. package/src/components/theme/Logo/Logo.jsx +35 -27
  234. package/src/components/theme/Logo/Logo.test.jsx +135 -1
  235. package/src/components/theme/Logout/Logout.jsx +36 -83
  236. package/src/components/theme/Navigation/Navigation.jsx +86 -171
  237. package/src/components/theme/PasswordReset/PasswordReset.jsx +7 -5
  238. package/src/components/theme/PasswordReset/RequestPasswordReset.jsx +95 -170
  239. package/src/components/theme/PreviewImage/PreviewImage.jsx +31 -15
  240. package/src/components/theme/PreviewImage/PreviewImage.test.js +53 -13
  241. package/src/components/theme/Register/Register.jsx +2 -4
  242. package/src/components/theme/Search/SearchTags.jsx +30 -60
  243. package/src/components/theme/SearchWidget/SearchWidget.jsx +49 -97
  244. package/src/components/theme/SearchWidget/SearchWidget.test.jsx +8 -0
  245. package/src/components/theme/Sitemap/Sitemap.jsx +24 -13
  246. package/src/components/theme/Sitemap/Sitemap.test.jsx +23 -2
  247. package/src/components/theme/TsTest/TsTest.test.tsx +11 -0
  248. package/src/components/theme/TsTest/TsTest.tsx +15 -0
  249. package/src/components/theme/View/AlbumView.jsx +21 -16
  250. package/src/components/theme/View/EventView.jsx +36 -25
  251. package/src/components/theme/View/FileView.jsx +23 -18
  252. package/src/components/theme/View/ImageView.jsx +40 -32
  253. package/src/components/theme/View/ImageView.test.jsx +4 -0
  254. package/src/components/theme/View/LinkView.jsx +53 -78
  255. package/src/components/theme/View/ListingView.jsx +36 -28
  256. package/src/components/theme/View/NewsItemView.jsx +16 -17
  257. package/src/components/theme/View/RenderBlocks.jsx +56 -27
  258. package/src/components/theme/View/RenderEmptyBlock.jsx +5 -0
  259. package/src/components/theme/View/SummaryView.jsx +49 -39
  260. package/src/components/theme/View/TabularView.jsx +59 -53
  261. package/src/components/theme/View/View.jsx +2 -0
  262. package/src/components/theme/Widgets/ImageWidget.stories.jsx +1 -2
  263. package/src/config/Blocks.jsx +46 -0
  264. package/src/config/Components.jsx +3 -1
  265. package/src/config/ControlPanels.js +0 -1
  266. package/src/config/Loadables.jsx +1 -1
  267. package/src/config/NonContentRoutes.jsx +1 -0
  268. package/src/config/RichTextEditor/Blocks.jsx +4 -5
  269. package/src/config/RichTextEditor/FromHTML.jsx +2 -2
  270. package/src/config/RichTextEditor/Plugins.jsx +2 -3
  271. package/src/config/RichTextEditor/Styles.jsx +1 -1
  272. package/src/config/RichTextEditor/ToHTML.jsx +12 -10
  273. package/src/config/RichTextEditor/index.js +2 -3
  274. package/src/config/Views.jsx +6 -4
  275. package/src/config/Widgets.jsx +3 -0
  276. package/src/config/index.js +36 -2
  277. package/src/config/server.js +2 -0
  278. package/src/constants/ActionTypes.js +4 -0
  279. package/src/constants/Indexes.js +3 -1
  280. package/src/express-middleware/devproxy.js +1 -1
  281. package/src/express-middleware/files.js +11 -9
  282. package/src/express-middleware/images.js +12 -5
  283. package/src/express-middleware/ok.js +16 -0
  284. package/src/express-middleware/robotstxt.js +1 -1
  285. package/src/express-middleware/sitemap.js +1 -1
  286. package/src/express-middleware/static.js +3 -3
  287. package/src/helpers/Blocks/Blocks.js +52 -6
  288. package/src/helpers/Blocks/Blocks.test.js +92 -13
  289. package/src/helpers/Extensions/index.js +2 -1
  290. package/src/helpers/Extensions/withBlockSchemaEnhancer.js +63 -61
  291. package/src/helpers/Extensions/withBlockSchemaEnhancer.test.js +145 -0
  292. package/src/helpers/FormValidation/FormValidation.js +37 -7
  293. package/src/helpers/FormValidation/FormValidation.test.js +32 -0
  294. package/src/helpers/Html/Html.jsx +2 -8
  295. package/src/helpers/Loadable/__mocks__/Loadable.js +18 -18
  296. package/src/helpers/MessageLabels/MessageLabels.js +39 -4
  297. package/src/helpers/ScrollToTop/ScrollToTop.jsx +5 -3
  298. package/src/helpers/Site/index.js +21 -0
  299. package/src/helpers/Url/Url.js +22 -1
  300. package/src/helpers/Url/Url.test.js +41 -0
  301. package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +190 -0
  302. package/src/helpers/Utils/Utils.js +35 -0
  303. package/src/helpers/Utils/Utils.test.js +13 -0
  304. package/src/helpers/Utils/usePagination.js +67 -14
  305. package/src/helpers/Utils/usePagination.test.js +115 -0
  306. package/src/helpers/index.js +15 -8
  307. package/src/hooks/client/useClient.js +11 -0
  308. package/src/hooks/clipboard/useClipboard.js +26 -0
  309. package/src/hooks/index.js +2 -0
  310. package/src/icons/grid-block.svg +11 -0
  311. package/src/middleware/api.js +203 -173
  312. package/src/middleware/blacklistRoutes.js +25 -22
  313. package/src/middleware/index.js +2 -2
  314. package/src/middleware/storeProtectLoadUtils.js +61 -62
  315. package/src/middleware/storeProtectLoadUtils.test.js +47 -43
  316. package/src/reducers/actions/actions.js +7 -5
  317. package/src/reducers/actions/actions.test.js +70 -0
  318. package/src/reducers/content/content.test.js +4 -4
  319. package/src/reducers/index.js +4 -0
  320. package/src/reducers/navigation/navigation.js +5 -5
  321. package/src/reducers/navigation/navigation.test.js +30 -0
  322. package/src/reducers/navroot/navroot.js +79 -0
  323. package/src/reducers/navroot/navroot.test.js +110 -0
  324. package/src/reducers/relations/relations.js +74 -46
  325. package/src/reducers/site/site.js +51 -0
  326. package/src/reducers/site/site.test.js +67 -0
  327. package/src/reducers/userSession/userSession.js +15 -1
  328. package/src/registry.js +2 -2
  329. package/src/routes.js +9 -0
  330. package/src/server.jsx +9 -0
  331. package/src/start-server.js +6 -2
  332. package/src/storybook.jsx +24 -38
  333. package/test-setup-config.js +11 -1
  334. package/theme/themes/pastanaga/collections/form.overrides +46 -0
  335. package/theme/themes/pastanaga/collections/menu.overrides +3 -2
  336. package/theme/themes/pastanaga/elements/container.overrides +5 -2
  337. package/theme/themes/pastanaga/elements/input.overrides +11 -1
  338. package/theme/themes/pastanaga/elements/label.overrides +10 -0
  339. package/theme/themes/pastanaga/elements/step.overrides +2 -1
  340. package/theme/themes/pastanaga/extras/blocks.less +25 -15
  341. package/theme/themes/pastanaga/extras/color-picker-widget.less +1 -1
  342. package/theme/themes/pastanaga/extras/contents.less +6 -1
  343. package/theme/themes/pastanaga/extras/draftjs.less +4 -4
  344. package/theme/themes/pastanaga/extras/grid.less +427 -0
  345. package/theme/themes/pastanaga/extras/login.less +3 -0
  346. package/theme/themes/pastanaga/extras/main.less +14 -7
  347. package/theme/themes/pastanaga/extras/react-dates-overrides.less +4 -2
  348. package/theme/themes/pastanaga/extras/search.less +7 -1
  349. package/theme/themes/pastanaga/extras/sidebar.less +5 -4
  350. package/theme/themes/pastanaga/extras/time-picker-overrides.less +5 -3
  351. package/theme/themes/pastanaga/extras/toc.less +29 -0
  352. package/theme/themes/pastanaga/extras/toolbar.less +6 -2
  353. package/theme/themes/pastanaga/extras/userscontrolpanel.less +17 -9
  354. package/theme/themes/pastanaga/extras/widgets.less +1 -1
  355. package/theme/themes/pastanaga/modules/rating.overrides +2 -1
  356. package/theme/themes/pastanaga-cms-ui/elements/container.overrides +2 -1
  357. package/theme/themes/pastanaga-cms-ui/extras/cms-ui.elements.container.less +6 -2
  358. package/theme/themes/pastanaga-cms-ui/extras/cms-ui.site.less +2 -2
  359. package/tsconfig.json +33 -0
  360. package/webpack-plugins/webpack-less-plugin.js +19 -0
  361. package/.yarn/install-state.gz +0 -0
  362. package/.yarn/releases/yarn-3.2.3.cjs +0 -783
  363. package/src/components/manage/Blocks/Teaser/utils.js +0 -44
  364. package/src/components/manage/Blocks/Teaser/utils.test.jsx +0 -229
  365. package/src/components/theme/Header/Header.md +0 -27
@@ -1,14 +1,11 @@
1
- /**
2
- * PersonalTools container.
3
- * @module components/manage/Toolbar/PersonalTools
4
- */
5
- import React, { Component } from 'react';
1
+ import React, { useState, useEffect } from 'react';
6
2
  import PropTypes from 'prop-types';
7
- import { connect } from 'react-redux';
8
- import { Link } from 'react-router-dom';
3
+ import { useDispatch, useSelector, shallowEqual } from 'react-redux';
4
+ import { Link, useLocation } from 'react-router-dom';
9
5
  import jwtDecode from 'jwt-decode';
10
6
  import cx from 'classnames';
11
- import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
7
+ import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
8
+
12
9
  import { Icon } from '@plone/volto/components';
13
10
  import { getUser } from '@plone/volto/actions';
14
11
  import { Pluggable } from '@plone/volto/components/manage/Pluggable';
@@ -17,12 +14,8 @@ import {
17
14
  getBaseUrl,
18
15
  userHasRoles,
19
16
  } from '@plone/volto/helpers';
20
- import { withRouter } from 'react-router-dom';
21
- import { compose } from 'redux';
22
-
23
17
  import logoutSVG from '@plone/volto/icons/log-out.svg';
24
18
  import rightArrowSVG from '@plone/volto/icons/right-key.svg';
25
-
26
19
  import backSVG from '@plone/volto/icons/back.svg';
27
20
  import cameraSVG from '@plone/volto/icons/camera.svg';
28
21
 
@@ -49,158 +42,107 @@ const messages = defineMessages({
49
42
  },
50
43
  });
51
44
 
52
- /**
53
- * Toolbar container class.
54
- * @class PersonalTools
55
- * @extends Component
56
- */
57
- class PersonalTools extends Component {
58
- /**
59
- * Property types.
60
- * @property {Object} propTypes Property types.
61
- * @static
62
- */
63
- static propTypes = {
64
- user: PropTypes.shape({
65
- fullname: PropTypes.string,
66
- email: PropTypes.string,
67
- home_page: PropTypes.string,
68
- location: PropTypes.string,
69
- }).isRequired,
70
- userId: PropTypes.string.isRequired,
71
- getUser: PropTypes.func.isRequired,
72
- loadComponent: PropTypes.func.isRequired,
73
- };
45
+ const PersonalTools = (props) => {
46
+ const dispatch = useDispatch();
47
+ const intl = useIntl();
48
+ const { pathname } = useLocation();
49
+ const [, setPushed] = useState(false);
50
+ const token = useSelector((state) => state.userSession.token, shallowEqual);
51
+ const user = useSelector((state) => state.users.user);
52
+ const userId = token ? jwtDecode(token).sub : '';
74
53
 
75
- componentDidMount() {
76
- this.props.getUser(this.props.userId);
77
- }
54
+ useEffect(() => {
55
+ dispatch(getUser(userId));
56
+ }, [dispatch, userId]);
78
57
 
79
- push = (selector) => {
80
- this.setState(() => ({
81
- pushed: true,
82
- }));
83
- this.props.loadComponent(selector);
58
+ const push = (selector) => {
59
+ setPushed(true);
60
+ props.loadComponent(selector);
84
61
  };
85
62
 
86
- pull = () => {
87
- this.props.unloadComponent();
63
+ const pull = () => {
64
+ props.unloadComponent();
88
65
  };
89
66
 
90
- /**
91
- * Render method.
92
- * @method render
93
- * @returns {string} Markup for the component.
94
- */
95
- render() {
96
- return (
97
- <div
98
- className={cx('personal-tools pastanaga-menu', {
99
- 'has-inner-actions': this.props.hasActions,
100
- })}
101
- style={{
102
- flex: this.props.theToolbar.current
103
- ? `0 0 ${
104
- this.props.theToolbar.current.getBoundingClientRect().width
105
- }px`
106
- : null,
107
- }}
108
- >
109
- <header className="header">
110
- <button className="back" onClick={this.pull}>
111
- <Icon
112
- name={backSVG}
113
- size="30px"
114
- title={this.props.intl.formatMessage(messages.back)}
115
- />
116
- </button>
117
- <div className="vertical divider" />
118
- <h2>
119
- {this.props.user.fullname
120
- ? this.props.user.fullname
121
- : this.props.user.username}
122
- </h2>
123
- <Link
124
- id="toolbar-logout"
125
- to={`${getBaseUrl(this.props.pathname)}/logout`}
126
- >
127
- <Icon
128
- className="logout"
129
- name={logoutSVG}
130
- size="30px"
131
- title={this.props.intl.formatMessage(messages.logout)}
132
- />
133
- </Link>
134
- </header>
135
- <div className={cx('avatar', { default: !this.props.user.portrait })}>
136
- {this.props.user.portrait ? (
137
- <img
138
- src={flattenToAppURL(this.props.user.portrait)}
139
- alt={this.props.intl.formatMessage(messages.userAvatar)}
140
- />
141
- ) : (
142
- <Icon name={cameraSVG} size="96px" />
143
- )}
144
- </div>
145
- {/* <Stats /> Maybe we can find a good fit in the future for this visual element */}
146
- <div className="pastanaga-menu-list">
147
- {/* This (probably also) should be a Component by itself*/}
148
- <ul>
67
+ return (
68
+ <div
69
+ className={cx('personal-tools pastanaga-menu', {
70
+ 'has-inner-actions': props.hasActions,
71
+ })}
72
+ style={{
73
+ flex: props.theToolbar.current
74
+ ? `0 0 ${props.theToolbar.current.getBoundingClientRect().width}px`
75
+ : null,
76
+ }}
77
+ >
78
+ <header className="header">
79
+ <button className="back" onClick={pull}>
80
+ <Icon
81
+ name={backSVG}
82
+ size="30px"
83
+ title={intl.formatMessage(messages.back)}
84
+ />
85
+ </button>
86
+ <div className="vertical divider" />
87
+ <h2>{user.fullname ? user.fullname : user.username}</h2>
88
+ <Link id="toolbar-logout" to={`${getBaseUrl(pathname)}/logout`}>
89
+ <Icon
90
+ className="logout"
91
+ name={logoutSVG}
92
+ size="30px"
93
+ title={intl.formatMessage(messages.logout)}
94
+ />
95
+ </Link>
96
+ </header>
97
+ <div className={cx('avatar', { default: !user.portrait })}>
98
+ {user.portrait ? (
99
+ <img
100
+ src={flattenToAppURL(user.portrait)}
101
+ alt={intl.formatMessage(messages.userAvatar)}
102
+ />
103
+ ) : (
104
+ <Icon name={cameraSVG} size="96px" />
105
+ )}
106
+ </div>
107
+ {/* <Stats /> Maybe we can find a good fit in the future for this visual element */}
108
+ <div className="pastanaga-menu-list">
109
+ {/* This (probably also) should be a Component by itself*/}
110
+ <ul>
111
+ <li>
112
+ <Link
113
+ id={intl.formatMessage(messages.profile)}
114
+ to="/personal-information"
115
+ >
116
+ <FormattedMessage id="Profile" defaultMessage="Profile" />
117
+ <Icon name={rightArrowSVG} size="24px" />
118
+ </Link>
119
+ </li>
120
+ <li>
121
+ <button
122
+ aria-label={intl.formatMessage(messages.preferences)}
123
+ onClick={() => push('preferences')}
124
+ >
125
+ <FormattedMessage id="Preferences" defaultMessage="Preferences" />
126
+ <Icon name={rightArrowSVG} size="24px" />
127
+ </button>
128
+ </li>
129
+
130
+ {userHasRoles(user, ['Site Administrator', 'Manager']) && (
149
131
  <li>
150
- <Link
151
- id={this.props.intl.formatMessage(messages.profile)}
152
- to="/personal-information"
153
- >
154
- <FormattedMessage id="Profile" defaultMessage="Profile" />
132
+ <Link to="/controlpanel">
133
+ <FormattedMessage id="Site Setup" defaultMessage="Site Setup" />
155
134
  <Icon name={rightArrowSVG} size="24px" />
156
135
  </Link>
157
136
  </li>
158
- <li>
159
- <button
160
- aria-label={this.props.intl.formatMessage(messages.preferences)}
161
- onClick={() => this.push('preferences')}
162
- >
163
- <FormattedMessage
164
- id="Preferences"
165
- defaultMessage="Preferences"
166
- />
167
- <Icon name={rightArrowSVG} size="24px" />
168
- </button>
169
- </li>
170
-
171
- {userHasRoles(this.props.user, [
172
- 'Site Administrator',
173
- 'Manager',
174
- ]) && (
175
- <li>
176
- <Link to="/controlpanel">
177
- <FormattedMessage
178
- id="Site Setup"
179
- defaultMessage="Site Setup"
180
- />
181
- <Icon name={rightArrowSVG} size="24px" />
182
- </Link>
183
- </li>
184
- )}
185
- <Pluggable name="toolbar-user-menu" />
186
- </ul>
187
- </div>
137
+ )}
138
+ <Pluggable name="toolbar-user-menu" />
139
+ </ul>
188
140
  </div>
189
- );
190
- }
191
- }
141
+ </div>
142
+ );
143
+ };
192
144
 
193
- export default compose(
194
- injectIntl,
195
- withRouter,
196
- connect(
197
- (state, props) => ({
198
- pathname: props.location.pathname,
199
- user: state.users.user,
200
- userId: state.userSession.token
201
- ? jwtDecode(state.userSession.token).sub
202
- : '',
203
- }),
204
- { getUser },
205
- ),
206
- )(PersonalTools);
145
+ PersonalTools.propTypes = {
146
+ loadComponent: PropTypes.func.isRequired,
147
+ };
148
+ export default PersonalTools;
@@ -591,8 +591,8 @@ class Toolbar extends Component {
591
591
  messages.shrinkToolbar,
592
592
  )}
593
593
  className={cx({
594
- [this.props.content?.review_state]: this.props.content
595
- ?.review_state,
594
+ [this.props.content?.review_state]:
595
+ this.props.content?.review_state,
596
596
  })}
597
597
  onClick={this.handleShrink}
598
598
  />
@@ -12,9 +12,9 @@ import {
12
12
  isInternalURL,
13
13
  URLUtils,
14
14
  } from '@plone/volto/helpers/Url/Url';
15
- import { matchPath } from 'react-router';
16
15
 
17
16
  import config from '@plone/volto/registry';
17
+ import cx from 'classnames';
18
18
 
19
19
  const UniversalLink = ({
20
20
  href,
@@ -66,11 +66,8 @@ const UniversalLink = ({
66
66
  }
67
67
  }
68
68
 
69
- const isBlacklisted =
70
- (config.settings.externalRoutes ?? []).find((route) =>
71
- matchPath(flattenToAppURL(url), route.match),
72
- )?.length > 0;
73
- const isExternal = !isInternalURL(url) || isBlacklisted;
69
+ const isExternal = !isInternalURL(url);
70
+
74
71
  const isDownload = (!isExternal && url.includes('@@download')) || download;
75
72
  const isDisplayFile =
76
73
  (!isExternal && url.includes('@@display-file')) || false;
@@ -92,19 +89,16 @@ const UniversalLink = ({
92
89
  );
93
90
 
94
91
  if (isExternal) {
92
+ const isTelephoneOrMail = checkedURL.isMail || checkedURL.isTelephone;
95
93
  tag = (
96
94
  <a
97
95
  href={url}
98
96
  title={title}
99
97
  target={
100
- !checkedURL.isMail &&
101
- !checkedURL.isTelephone &&
102
- !(openLinkInNewTab === false)
103
- ? '_blank'
104
- : null
98
+ !isTelephoneOrMail && !(openLinkInNewTab === false) ? '_blank' : null
105
99
  }
106
100
  rel="noopener noreferrer"
107
- className={className}
101
+ className={cx({ external: !isTelephoneOrMail }, className)}
108
102
  {...props}
109
103
  >
110
104
  {children}
@@ -157,6 +157,43 @@ describe('UniversalLink', () => {
157
157
  );
158
158
  });
159
159
 
160
+ it('UniversalLink renders external link where link is blacklisted', () => {
161
+ const notInEN =
162
+ /^(?!.*(#|\/en|\/static|\/controlpanel|\/cypress|\/login|\/logout|\/contact-form)).*$/;
163
+ config.settings.externalRoutes = [
164
+ {
165
+ match: {
166
+ path: notInEN,
167
+ exact: false,
168
+ strict: false,
169
+ },
170
+ url(payload) {
171
+ return payload.location.pathname;
172
+ },
173
+ },
174
+ ];
175
+
176
+ const { getByTitle } = render(
177
+ <Provider store={store}>
178
+ <MemoryRouter>
179
+ <UniversalLink
180
+ href="http://localhost:3000/blacklisted-app"
181
+ title="External blacklisted app"
182
+ >
183
+ <h1>Title</h1>
184
+ </UniversalLink>
185
+ </MemoryRouter>
186
+ </Provider>,
187
+ );
188
+
189
+ expect(getByTitle('External blacklisted app').getAttribute('target')).toBe(
190
+ '_blank',
191
+ );
192
+ expect(getByTitle('External blacklisted app').getAttribute('rel')).toBe(
193
+ 'noopener noreferrer',
194
+ );
195
+ });
196
+
160
197
  it('check UniversalLink does not break with error in item', () => {
161
198
  const component = renderer.create(
162
199
  <Provider store={store}>
@@ -47,10 +47,8 @@ export const defaultActionsInfo = ({ intl }) => ({
47
47
  const AlignWidget = (props) => {
48
48
  const intl = useIntl();
49
49
 
50
- const {
51
- actions = ['left', 'right', 'center', 'full'],
52
- actionsInfoMap,
53
- } = props;
50
+ const { actions = ['left', 'right', 'center', 'full'], actionsInfoMap } =
51
+ props;
54
52
 
55
53
  const actionsInfo = {
56
54
  ...defaultActionsInfo({ intl }),
@@ -325,7 +325,9 @@ class ArrayWidget extends Component {
325
325
  : this.props.choices
326
326
  ? [
327
327
  ...choices,
328
- ...(this.props.noValueOption && !this.props.default
328
+ ...(this.props.noValueOption &&
329
+ (this.props.default === undefined ||
330
+ this.props.default === null)
329
331
  ? [
330
332
  {
331
333
  label: this.props.intl.formatMessage(
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
- import { waitFor } from '@testing-library/react';
5
+ import { waitFor, render, fireEvent } from '@testing-library/react';
6
6
 
7
7
  import ArrayWidget from './ArrayWidget';
8
8
 
@@ -41,3 +41,47 @@ test('renders an array widget component', async () => {
41
41
  await waitFor(() => {});
42
42
  expect(component.toJSON()).toMatchSnapshot();
43
43
  });
44
+
45
+ test("No 'No value' option when default value is 0", async () => {
46
+ const store = mockStore({
47
+ intl: {
48
+ locale: 'en',
49
+ messages: {},
50
+ },
51
+ });
52
+
53
+ const choices = [
54
+ ['0', 'None'],
55
+ ['1', 'One'],
56
+ ];
57
+
58
+ const value = {
59
+ value: '0',
60
+ label: 'None',
61
+ };
62
+
63
+ const _default = 0;
64
+
65
+ const { container } = render(
66
+ <Provider store={store}>
67
+ <ArrayWidget
68
+ id="my-field"
69
+ title="My field"
70
+ fieldSet="default"
71
+ choices={choices}
72
+ default={_default}
73
+ value={value}
74
+ noValueOption={true}
75
+ onChange={() => {}}
76
+ onBlur={() => {}}
77
+ onClick={() => {}}
78
+ />
79
+ </Provider>,
80
+ );
81
+
82
+ fireEvent.mouseDown(
83
+ container.querySelector('.react-select__dropdown-indicator'),
84
+ { button: 0 },
85
+ );
86
+ expect(container).toMatchSnapshot();
87
+ });
@@ -51,7 +51,12 @@ const ColorPickerWidget = (props) => {
51
51
  onClick={(e) => {
52
52
  e.preventDefault();
53
53
  e.stopPropagation();
54
- onChange(id, color.name);
54
+ onChange(
55
+ id,
56
+ value === color.name
57
+ ? props.missing_value
58
+ : color.name,
59
+ );
55
60
  }}
56
61
  active={value === color.name}
57
62
  circular
@@ -7,14 +7,16 @@ import ColorPickerWidget from './ColorPickerWidget';
7
7
 
8
8
  const mockStore = configureStore();
9
9
 
10
- const withStateManagement = (Component) => ({ ...props }) => {
11
- const [value, setValue] = React.useState(props.value || null);
12
- const onChange = (id, value) => {
13
- setValue(value);
14
- };
10
+ const withStateManagement =
11
+ (Component) =>
12
+ ({ ...props }) => {
13
+ const [value, setValue] = React.useState(props.value || null);
14
+ const onChange = (id, value) => {
15
+ setValue(value);
16
+ };
15
17
 
16
- return <Component {...props} onChange={onChange} value={value} />;
17
- };
18
+ return <Component {...props} onChange={onChange} value={value} />;
19
+ };
18
20
 
19
21
  describe('ColorPickerWidget', () => {
20
22
  const COLORS = [
@@ -179,14 +179,8 @@ export class DatetimeWidgetComponent extends Component {
179
179
  onFocusChange = ({ focused }) => this.setState({ focused });
180
180
 
181
181
  render() {
182
- const {
183
- id,
184
- resettable,
185
- intl,
186
- reactDates,
187
- widgetOptions,
188
- lang,
189
- } = this.props;
182
+ const { id, resettable, intl, reactDates, widgetOptions, lang } =
183
+ this.props;
190
184
  const noPastDates =
191
185
  this.props.noPastDates || widgetOptions?.pattern_options?.noPastDates;
192
186
  const moment = this.props.moment.default;
@@ -11,7 +11,7 @@ import { injectIntl } from 'react-intl';
11
11
  import deleteSVG from '@plone/volto/icons/delete.svg';
12
12
  import { Icon, FormFieldWrapper } from '@plone/volto/components';
13
13
  import loadable from '@loadable/component';
14
- import { flattenToAppURL } from '@plone/volto/helpers';
14
+ import { flattenToAppURL, validateFileUploadSize } from '@plone/volto/helpers';
15
15
  import { defineMessages, useIntl } from 'react-intl';
16
16
 
17
17
  const imageMimetypes = [
@@ -95,6 +95,7 @@ const FileWidget = (props) => {
95
95
  */
96
96
  const onDrop = (files) => {
97
97
  const file = files[0];
98
+ if (!validateFileUploadSize(file, intl.formatMessage)) return;
98
99
  readAsDataURL(file).then((data) => {
99
100
  const fields = data.match(/^data:(.*);(.*),(.*)$/);
100
101
  onChange(id, {
@@ -96,7 +96,7 @@ class FormFieldWrapper extends Component {
96
96
  {this.props.children}
97
97
 
98
98
  {map(error, (message) => (
99
- <Label key={message} basic color="red" pointing>
99
+ <Label key={message} basic color="red" className="form-error-label">
100
100
  {message}
101
101
  </Label>
102
102
  ))}
@@ -21,8 +21,7 @@ const messages = defineMessages({
21
21
  defaultMessage: "This is a reserved name and can't be used",
22
22
  },
23
23
  invalidCharacters: {
24
- id:
25
- 'Only lowercase letters (a-z) without accents, numbers (0-9), and the characters "-", "_", and "." are allowed.',
24
+ id: 'Only lowercase letters (a-z) without accents, numbers (0-9), and the characters "-", "_", and "." are allowed.',
26
25
  defaultMessage:
27
26
  'Only lowercase letters (a-z) without accents, numbers (0-9), and the characters "-", "_", and "." are allowed.',
28
27
  },
@@ -312,15 +312,8 @@ export class ObjectBrowserWidgetComponent extends Component {
312
312
  * @returns {string} Markup for the component.
313
313
  */
314
314
  render() {
315
- const {
316
- id,
317
- description,
318
- fieldSet,
319
- value,
320
- mode,
321
- onChange,
322
- isDisabled,
323
- } = this.props;
315
+ const { id, description, fieldSet, value, mode, onChange, isDisabled } =
316
+ this.props;
324
317
 
325
318
  let items = compact(!isArray(value) && value ? [value] : value || []);
326
319
 
@@ -427,7 +427,7 @@ class RecurrenceWidget extends Component {
427
427
  break;
428
428
  }
429
429
 
430
- if (value) {
430
+ if (value === 0 || value) {
431
431
  //set value
432
432
  values[field] = value;
433
433
  } else {
@@ -734,15 +734,8 @@ class RecurrenceWidget extends Component {
734
734
  render() {
735
735
  const { open, dimmer, rruleSet, formValues, RRULE_LANGUAGE } = this.state;
736
736
 
737
- const {
738
- id,
739
- title,
740
- required,
741
- description,
742
- error,
743
- fieldSet,
744
- intl,
745
- } = this.props;
737
+ const { id, title, required, description, error, fieldSet, intl } =
738
+ this.props;
746
739
 
747
740
  return (
748
741
  <Form.Field
@@ -27,10 +27,10 @@ const messages = defineMessages({
27
27
  });
28
28
 
29
29
  const ORDINAL_NUMBERS = {
30
- '1': 'first',
31
- '2': 'second',
32
- '3': 'third',
33
- '4': 'fourth',
30
+ 1: 'first',
31
+ 2: 'second',
32
+ 3: 'third',
33
+ 4: 'fourth',
34
34
  '-1': 'last',
35
35
  };
36
36