@plone/volto 19.0.0-alpha.9 → 19.1.0

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 (535) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +26 -15
  3. package/AGENTS.md +47 -0
  4. package/CHANGELOG.md +543 -12
  5. package/README.md +22 -19
  6. package/babel.js +1 -9
  7. package/cypress/support/guillotina.js +1 -0
  8. package/cypress.config.js +1 -0
  9. package/global-test-setup.js +1 -2
  10. package/locales/af/LC_MESSAGES/volto.po +5516 -0
  11. package/locales/af.json +1 -1
  12. package/locales/ar/LC_MESSAGES/volto.po +5516 -0
  13. package/locales/ar.json +1 -1
  14. package/locales/bg/LC_MESSAGES/volto.po +5516 -0
  15. package/locales/bg.json +1 -1
  16. package/locales/bn/LC_MESSAGES/volto.po +5516 -0
  17. package/locales/bn.json +1 -1
  18. package/locales/ca/LC_MESSAGES/volto.po +551 -359
  19. package/locales/ca.json +1 -1
  20. package/locales/cs/LC_MESSAGES/volto.po +5516 -0
  21. package/locales/cs.json +1 -1
  22. package/locales/cy/LC_MESSAGES/volto.po +5516 -0
  23. package/locales/cy.json +1 -1
  24. package/locales/da/LC_MESSAGES/volto.po +5516 -0
  25. package/locales/da.json +1 -1
  26. package/locales/de/LC_MESSAGES/volto.po +222 -29
  27. package/locales/de.json +1 -1
  28. package/locales/el/LC_MESSAGES/volto.po +5516 -0
  29. package/locales/el.json +1 -1
  30. package/locales/en/LC_MESSAGES/volto.po +211 -15
  31. package/locales/en.json +1 -1
  32. package/locales/en_AU/LC_MESSAGES/volto.po +5516 -0
  33. package/locales/en_AU.json +1 -1
  34. package/locales/en_GB/LC_MESSAGES/volto.po +5516 -0
  35. package/locales/en_GB.json +1 -1
  36. package/locales/eo/LC_MESSAGES/volto.po +5516 -0
  37. package/locales/eo.json +1 -1
  38. package/locales/es/LC_MESSAGES/volto.po +336 -145
  39. package/locales/es.json +1 -1
  40. package/locales/et/LC_MESSAGES/volto.po +5516 -0
  41. package/locales/et.json +1 -1
  42. package/locales/eu/LC_MESSAGES/volto.po +413 -222
  43. package/locales/eu.json +1 -1
  44. package/locales/fa/LC_MESSAGES/volto.po +5516 -0
  45. package/locales/fa.json +1 -1
  46. package/locales/fi/LC_MESSAGES/volto.po +212 -20
  47. package/locales/fi.json +1 -1
  48. package/locales/fr/LC_MESSAGES/volto.po +369 -178
  49. package/locales/fr.json +1 -1
  50. package/locales/fu/LC_MESSAGES/volto.po +5516 -0
  51. package/locales/fu.json +1 -1
  52. package/locales/gl/LC_MESSAGES/volto.po +5516 -0
  53. package/locales/gl.json +1 -1
  54. package/locales/he/LC_MESSAGES/volto.po +5516 -0
  55. package/locales/he.json +1 -1
  56. package/locales/hi/LC_MESSAGES/volto.po +220 -23
  57. package/locales/hi.json +1 -1
  58. package/locales/hr/LC_MESSAGES/volto.po +5516 -0
  59. package/locales/hr.json +1 -1
  60. package/locales/hu/LC_MESSAGES/volto.po +5516 -0
  61. package/locales/hu.json +1 -1
  62. package/locales/hy/LC_MESSAGES/volto.po +5516 -0
  63. package/locales/hy.json +1 -1
  64. package/locales/id/LC_MESSAGES/volto.po +5516 -0
  65. package/locales/id.json +1 -1
  66. package/locales/it/LC_MESSAGES/volto.po +236 -39
  67. package/locales/it.json +1 -1
  68. package/locales/ja/LC_MESSAGES/volto.po +254 -61
  69. package/locales/ja.json +1 -1
  70. package/locales/ka/LC_MESSAGES/volto.po +5516 -0
  71. package/locales/ka.json +1 -1
  72. package/locales/kn/LC_MESSAGES/volto.po +5516 -0
  73. package/locales/kn.json +1 -1
  74. package/locales/ko/LC_MESSAGES/volto.po +5516 -0
  75. package/locales/ko.json +1 -1
  76. package/locales/lt/LC_MESSAGES/volto.po +5516 -0
  77. package/locales/lt.json +1 -1
  78. package/locales/lv/LC_MESSAGES/volto.po +5516 -0
  79. package/locales/lv.json +1 -1
  80. package/locales/mi/LC_MESSAGES/volto.po +5516 -0
  81. package/locales/mi.json +1 -1
  82. package/locales/mk/LC_MESSAGES/volto.po +5516 -0
  83. package/locales/mk.json +1 -1
  84. package/locales/my/LC_MESSAGES/volto.po +5516 -0
  85. package/locales/my.json +1 -1
  86. package/locales/nb_NO/LC_MESSAGES/volto.po +5516 -0
  87. package/locales/nb_NO.json +1 -1
  88. package/locales/nl/LC_MESSAGES/volto.po +264 -71
  89. package/locales/nl.json +1 -1
  90. package/locales/nn/LC_MESSAGES/volto.po +5516 -0
  91. package/locales/nn.json +1 -1
  92. package/locales/pl/LC_MESSAGES/volto.po +5516 -0
  93. package/locales/pl.json +1 -1
  94. package/locales/pt/LC_MESSAGES/volto.po +862 -670
  95. package/locales/pt.json +1 -1
  96. package/locales/pt_BR/LC_MESSAGES/volto.po +216 -25
  97. package/locales/pt_BR.json +1 -1
  98. package/locales/rm/LC_MESSAGES/volto.po +5516 -0
  99. package/locales/rm.json +1 -1
  100. package/locales/ro/LC_MESSAGES/volto.po +248 -57
  101. package/locales/ro.json +1 -1
  102. package/locales/ru/LC_MESSAGES/volto.po +211 -19
  103. package/locales/ru.json +1 -1
  104. package/locales/sk/LC_MESSAGES/volto.po +5516 -0
  105. package/locales/sk.json +1 -1
  106. package/locales/sl/LC_MESSAGES/volto.po +5516 -0
  107. package/locales/sl.json +1 -1
  108. package/locales/sm/LC_MESSAGES/volto.po +5516 -0
  109. package/locales/sm.json +1 -1
  110. package/locales/sq/LC_MESSAGES/volto.po +5516 -0
  111. package/locales/sq.json +1 -1
  112. package/locales/sr/LC_MESSAGES/volto.po +5516 -0
  113. package/locales/sr.json +1 -1
  114. package/locales/sr@cyrl/LC_MESSAGES/volto.po +5516 -0
  115. package/locales/sr@cyrl.json +1 -1
  116. package/locales/sr@latn/LC_MESSAGES/volto.po +5516 -0
  117. package/locales/sr@latn.json +1 -1
  118. package/locales/sv/LC_MESSAGES/volto.po +5516 -0
  119. package/locales/sv.json +1 -1
  120. package/locales/ta/LC_MESSAGES/volto.po +5516 -0
  121. package/locales/ta.json +1 -1
  122. package/locales/te/LC_MESSAGES/volto.po +5516 -0
  123. package/locales/te.json +1 -1
  124. package/locales/th/LC_MESSAGES/volto.po +5516 -0
  125. package/locales/th.json +1 -1
  126. package/locales/to/LC_MESSAGES/volto.po +5516 -0
  127. package/locales/to.json +1 -1
  128. package/locales/tr/LC_MESSAGES/volto.po +5516 -0
  129. package/locales/tr.json +1 -1
  130. package/locales/uk/LC_MESSAGES/volto.po +5516 -0
  131. package/locales/uk.json +1 -1
  132. package/locales/vi/LC_MESSAGES/volto.po +5516 -0
  133. package/locales/vi.json +1 -1
  134. package/locales/volto.pot +205 -14
  135. package/locales/zh_CN/LC_MESSAGES/volto.po +211 -19
  136. package/locales/zh_CN.json +1 -1
  137. package/locales/zh_Hant/LC_MESSAGES/volto.po +5516 -0
  138. package/locales/zh_Hant.json +1 -1
  139. package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +5516 -0
  140. package/locales/zh_Hant_HK.json +1 -1
  141. package/package.json +71 -149
  142. package/razzle.config.js +16 -25
  143. package/src/actions/blockTypes/blockTypes.ts +24 -0
  144. package/src/actions/controlpanels/controlpanels.js +7 -12
  145. package/src/actions/controlpanels/controlpanels.test.js +2 -3
  146. package/src/components/manage/Actions/Actions.test.jsx +1 -5
  147. package/src/components/manage/Add/Add.jsx +15 -10
  148. package/src/components/manage/Add/Add.test.jsx +10 -3
  149. package/src/components/manage/Aliases/Aliases.test.jsx +5 -2
  150. package/src/components/manage/BlockChooser/BlockChooser.jsx +8 -10
  151. package/src/components/manage/Blocks/Block/BlocksForm.jsx +10 -7
  152. package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +3 -14
  153. package/src/components/manage/Blocks/Block/Edit.jsx +19 -10
  154. package/src/components/manage/Blocks/Block/Order/Item.jsx +33 -14
  155. package/src/components/manage/Blocks/Block/Order/Item.test.jsx +90 -0
  156. package/src/components/manage/Blocks/Block/Order/Order.jsx +116 -67
  157. package/src/components/manage/Blocks/Block/Order/utilities.js +28 -11
  158. package/src/components/manage/Blocks/Block/Settings.test.jsx +1 -5
  159. package/src/components/manage/Blocks/Grid/View.jsx +14 -11
  160. package/src/components/manage/Blocks/Grid/context.js +3 -0
  161. package/src/components/manage/Blocks/HTML/Edit.test.jsx +1 -5
  162. package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +2 -5
  163. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +2 -5
  164. package/src/components/manage/Blocks/Listing/Edit.jsx +1 -0
  165. package/src/components/manage/Blocks/Listing/ListingBody.jsx +4 -0
  166. package/src/components/manage/Blocks/Maps/Body.jsx +37 -0
  167. package/src/components/manage/Blocks/Maps/Edit.jsx +6 -21
  168. package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +1 -5
  169. package/src/components/manage/Blocks/Maps/View.jsx +16 -25
  170. package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +1 -6
  171. package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +22 -1
  172. package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +1 -6
  173. package/src/components/manage/Blocks/Search/components/SortOn.jsx +8 -2
  174. package/src/components/manage/Blocks/Search/components/ToggleFacet.jsx +14 -0
  175. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +10 -2
  176. package/src/components/manage/Blocks/Teaser/View.jsx +0 -1
  177. package/src/components/manage/Blocks/Teaser/utils.js +13 -0
  178. package/src/components/manage/Blocks/Teaser/utils.test.js +34 -0
  179. package/src/components/manage/Blocks/Title/Edit.jsx +5 -0
  180. package/src/components/manage/Blocks/Video/Body.jsx +69 -43
  181. package/src/components/manage/Blocks/Video/Body.test.jsx +122 -5
  182. package/src/components/manage/Blocks/Video/Edit.jsx +20 -2
  183. package/src/components/manage/Blocks/Video/Edit.test.jsx +6 -0
  184. package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +1 -5
  185. package/src/components/manage/Blocks/Video/View.jsx +1 -0
  186. package/src/components/manage/Blocks/Video/View.test.jsx +29 -15
  187. package/src/components/manage/Blocks/Video/schema.js +14 -1
  188. package/src/components/manage/Contents/Contents.jsx +854 -747
  189. package/src/components/manage/Contents/Contents.test.jsx +9 -10
  190. package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +4 -3
  191. package/src/components/manage/Contents/ContentsIndexHeader.jsx +47 -81
  192. package/src/components/manage/Contents/ContentsIndexHeader.test.jsx +10 -3
  193. package/src/components/manage/Contents/ContentsItem.jsx +226 -278
  194. package/src/components/manage/Contents/ContentsItem.test.jsx +10 -6
  195. package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +1 -5
  196. package/src/components/manage/Contents/ContentsRenameModal.test.jsx +1 -5
  197. package/src/components/manage/Contents/ContentsTagsModal.test.jsx +1 -5
  198. package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +1 -5
  199. package/src/components/manage/Contents/DropZoneContent.jsx +339 -0
  200. package/src/components/manage/Contents/__mocks__/index.tsx +2 -18
  201. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +7 -0
  202. package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +7 -4
  203. package/src/components/manage/Controlpanels/Aliases.test.jsx +8 -9
  204. package/src/components/manage/Controlpanels/BlockType.tsx +165 -0
  205. package/src/components/manage/Controlpanels/BlockTypes.tsx +145 -0
  206. package/src/components/manage/Controlpanels/ContentType.jsx +131 -222
  207. package/src/components/manage/Controlpanels/ContentType.test.jsx +13 -14
  208. package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +12 -9
  209. package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -1
  210. package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
  211. package/src/components/manage/Controlpanels/ContentTypes.test.jsx +7 -4
  212. package/src/components/manage/Controlpanels/Controlpanel.jsx +122 -218
  213. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +8 -33
  214. package/src/components/manage/Controlpanels/Controlpanels.jsx +28 -5
  215. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +23 -8
  216. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +9 -0
  217. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +7 -4
  218. package/src/components/manage/Controlpanels/ModerateComments.jsx +8 -0
  219. package/src/components/manage/Controlpanels/ModerateComments.test.jsx +7 -4
  220. package/src/components/manage/Controlpanels/Relations/Relations.jsx +1 -1
  221. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +8 -9
  222. package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -6
  223. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +8 -9
  224. package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -4
  225. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +8 -9
  226. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +10 -4
  227. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +628 -631
  228. package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
  229. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +70 -10
  230. package/src/components/manage/Controlpanels/VersionOverview.jsx +19 -6
  231. package/src/components/manage/Delete/Delete.test.jsx +13 -8
  232. package/src/components/manage/Diff/Diff.jsx +201 -298
  233. package/src/components/manage/Diff/Diff.test.jsx +8 -10
  234. package/src/components/manage/Diff/DiffField.test.jsx +1 -6
  235. package/src/components/manage/Display/Display.test.jsx +2 -11
  236. package/src/components/manage/Edit/Edit.test.jsx +12 -11
  237. package/src/components/manage/Form/BlockDataForm.test.jsx +1 -5
  238. package/src/components/manage/Form/Field.jsx +1 -69
  239. package/src/components/manage/Form/Form.jsx +17 -4
  240. package/src/components/manage/Form/Form.test.jsx +130 -5
  241. package/src/components/manage/Form/InlineForm.test.jsx +1 -5
  242. package/src/components/manage/Form/ModalForm.jsx +175 -97
  243. package/src/components/manage/Form/ModalForm.test.jsx +27 -5
  244. package/src/components/manage/Form/__mocks__/index.tsx +9 -27
  245. package/src/components/manage/History/History.jsx +209 -300
  246. package/src/components/manage/History/History.test.jsx +20 -9
  247. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +7 -4
  248. package/src/components/manage/Multilingual/CompareLanguages.jsx +6 -6
  249. package/src/components/manage/Multilingual/CreateTranslation.jsx +16 -13
  250. package/src/components/manage/Multilingual/ManageTranslations.jsx +5 -5
  251. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +15 -12
  252. package/src/components/manage/Multilingual/TranslationObject.jsx +11 -8
  253. package/src/components/manage/Preferences/ChangePassword.test.jsx +8 -9
  254. package/src/components/manage/Preferences/PersonalPreferences.jsx +8 -5
  255. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +10 -23
  256. package/src/components/manage/Rules/Rules.test.jsx +5 -2
  257. package/src/components/manage/Sharing/Sharing.jsx +21 -15
  258. package/src/components/manage/Sharing/Sharing.test.jsx +9 -6
  259. package/src/components/manage/Sidebar/ObjectBrowser.jsx +10 -0
  260. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +25 -5
  261. package/src/components/manage/Sidebar/ObjectBrowserBody.test.jsx +52 -0
  262. package/src/components/manage/Sidebar/Sidebar.jsx +2 -0
  263. package/src/components/manage/Sidebar/Sidebar.test.jsx +4 -1
  264. package/src/components/manage/Sidebar/SidebarPortal.test.tsx +42 -0
  265. package/src/components/manage/Sidebar/SidebarPortal.tsx +48 -0
  266. package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +1 -0
  267. package/src/components/manage/Toast/Toast.jsx +32 -0
  268. package/src/components/manage/Toast/Toast.test.jsx +9 -5
  269. package/src/components/manage/Toolbar/PersonalTools.test.jsx +15 -0
  270. package/src/components/manage/Toolbar/Toolbar.jsx +109 -12
  271. package/src/components/manage/Toolbar/Toolbar.test.jsx +15 -10
  272. package/src/components/manage/Toolbar/Types.crash.test.jsx +48 -0
  273. package/src/components/manage/Toolbar/Types.jsx +6 -4
  274. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +16 -0
  275. package/src/components/manage/UniversalLink/UniversalLink.tsx +1 -0
  276. package/src/components/manage/Widgets/AlignWidget.stories.jsx +9 -0
  277. package/src/components/manage/Widgets/AlignWidget.test.tsx +95 -0
  278. package/src/components/manage/Widgets/{AlignWidget.jsx → AlignWidget.tsx} +23 -7
  279. package/src/components/manage/Widgets/ArrayWidget.jsx +111 -88
  280. package/src/components/manage/Widgets/ArrayWidget.test.jsx +1 -12
  281. package/src/components/manage/Widgets/BlockAlignment.stories.tsx +104 -0
  282. package/src/components/manage/Widgets/BlockAlignment.test.tsx +104 -0
  283. package/src/components/manage/Widgets/BlockAlignment.tsx +88 -0
  284. package/src/components/manage/Widgets/BlockWidth.stories.tsx +69 -0
  285. package/src/components/manage/Widgets/BlockWidth.test.tsx +62 -0
  286. package/src/components/manage/Widgets/BlockWidth.tsx +101 -0
  287. package/src/components/manage/Widgets/ButtonsWidget.stories.jsx +61 -0
  288. package/src/components/manage/Widgets/ButtonsWidget.test.tsx +138 -0
  289. package/src/components/manage/Widgets/ButtonsWidget.tsx +195 -0
  290. package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +1 -6
  291. package/src/components/manage/Widgets/DatetimeWidget.jsx +98 -54
  292. package/src/components/manage/Widgets/DatetimeWidget.test.jsx +56 -6
  293. package/src/components/manage/Widgets/FileWidget.jsx +7 -0
  294. package/src/components/manage/Widgets/FormFieldWrapper.jsx +143 -163
  295. package/src/components/manage/Widgets/ImageWidget.jsx +18 -5
  296. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +6 -0
  297. package/src/components/manage/Widgets/ObjectListWidget.test.jsx +2 -11
  298. package/src/components/manage/Widgets/ObjectWidget.test.jsx +1 -5
  299. package/src/components/manage/Widgets/QueryWidget.jsx +137 -9
  300. package/src/components/manage/Widgets/QuerystringWidget.test.jsx +3 -1
  301. package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +1 -6
  302. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +1 -6
  303. package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +56 -50
  304. package/src/components/manage/Widgets/RegistryImageWidget.jsx +1 -1
  305. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +1 -0
  306. package/src/components/manage/Widgets/SchemaWidget.test.jsx +1 -6
  307. package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +1 -6
  308. package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +1 -6
  309. package/src/components/manage/Widgets/SelectStyling.jsx +52 -20
  310. package/src/components/manage/Widgets/SelectWidget.test.jsx +1 -6
  311. package/src/components/manage/Widgets/Size.stories.tsx +69 -0
  312. package/src/components/manage/Widgets/Size.test.tsx +59 -0
  313. package/src/components/manage/Widgets/Size.tsx +78 -0
  314. package/src/components/manage/Widgets/TextWidget.jsx +4 -0
  315. package/src/components/manage/Widgets/TimeWidget.test.jsx +1 -6
  316. package/src/components/manage/Widgets/TokenWidget.jsx +142 -186
  317. package/src/components/manage/Widgets/TokenWidget.test.jsx +1 -6
  318. package/src/components/manage/Widgets/UrlWidget.jsx +47 -18
  319. package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +2 -11
  320. package/src/components/manage/Widgets/__mocks__/index.tsx +33 -51
  321. package/src/components/manage/Widgets/index.tsx +21 -0
  322. package/src/components/manage/Workflow/Workflow.test.jsx +2 -11
  323. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -0
  324. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +30 -0
  325. package/src/components/theme/App/App.jsx +5 -1
  326. package/src/components/theme/App/App.test.jsx +13 -10
  327. package/src/components/theme/Comments/CommentEditModal.test.jsx +1 -5
  328. package/src/components/theme/Comments/Comments.test.jsx +2 -11
  329. package/src/components/theme/ConnectionRefused/ConnectionRefused.jsx +3 -2
  330. package/src/components/theme/ContactForm/ContactForm.test.jsx +14 -13
  331. package/src/components/theme/Image/Image.jsx +14 -5
  332. package/src/components/theme/Image/Image.test.jsx +247 -146
  333. package/src/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.tsx +7 -0
  334. package/src/components/theme/LanguageSelector/LanguageSelector.tsx +3 -3
  335. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +42 -12
  336. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +6 -3
  337. package/src/components/theme/PasswordReset/PasswordReset.jsx +108 -191
  338. package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +1 -5
  339. package/src/components/theme/Register/Register.test.jsx +1 -5
  340. package/src/components/theme/Search/Search.jsx +230 -327
  341. package/src/components/theme/Search/Search.test.jsx +14 -14
  342. package/src/components/theme/Sitemap/Sitemap.jsx +22 -30
  343. package/src/components/theme/Sitemap/Sitemap.stories.jsx +82 -0
  344. package/src/components/theme/Sitemap/Sitemap.test.jsx +18 -0
  345. package/src/components/theme/SlotRenderer/SlotRenderer.tsx +12 -6
  346. package/src/components/theme/Unauthorized/Unauthorized.jsx +27 -24
  347. package/src/components/theme/Unauthorized/Unauthorized.test.jsx +31 -2
  348. package/src/components/theme/VideoEmbed/VideoEmbed.jsx +100 -0
  349. package/src/components/theme/View/EventDatesInfo.test.jsx +1 -6
  350. package/src/components/theme/View/EventView.stories.jsx +89 -0
  351. package/src/components/theme/View/EventView.test.jsx +1 -6
  352. package/src/components/theme/View/FileView.stories.jsx +50 -0
  353. package/src/components/theme/View/ImageView.jsx +2 -1
  354. package/src/components/theme/View/ImageView.test.jsx +3 -0
  355. package/src/components/theme/View/LinkView.stories.jsx +57 -0
  356. package/src/components/theme/View/ListingView.stories.jsx +70 -0
  357. package/src/components/theme/View/NewsItemView.stories.jsx +58 -0
  358. package/src/components/theme/View/RenderBlocks.jsx +8 -10
  359. package/src/components/theme/View/RenderBlocks.stories.jsx +112 -0
  360. package/src/components/theme/View/RenderBlocks.test.jsx +14 -4
  361. package/src/components/theme/View/SummaryView.stories.jsx +71 -0
  362. package/src/components/theme/View/TabularView.stories.jsx +66 -0
  363. package/src/components/theme/View/View.jsx +8 -1
  364. package/src/components/theme/View/View.test.jsx +37 -24
  365. package/src/components/theme/Widgets/DateWidget.jsx +4 -5
  366. package/src/components/theme/Widgets/DatetimeWidget.jsx +4 -5
  367. package/src/components/theme/Widgets/ImageWidget.test.jsx +31 -11
  368. package/src/components/theme/Widgets/RichTextWidget.jsx +1 -1
  369. package/src/config/Blocks.jsx +3 -0
  370. package/src/config/ControlPanels.js +2 -0
  371. package/src/config/Loadables.jsx +1 -5
  372. package/src/config/Widgets.jsx +7 -0
  373. package/src/config/index.js +10 -1
  374. package/src/config/slots.js +19 -0
  375. package/src/config/validation.ts +8 -0
  376. package/src/constants/ActionTypes.js +1 -0
  377. package/src/express-middleware/devproxy.js +3 -1
  378. package/src/express-middleware/files.js +1 -0
  379. package/src/express-middleware/files.test.js +59 -0
  380. package/src/express-middleware/images.js +1 -0
  381. package/src/express-middleware/images.test.js +50 -0
  382. package/src/helpers/Api/Api.js +2 -2
  383. package/src/helpers/AuthToken/AuthToken.js +1 -6
  384. package/src/helpers/Blocks/Blocks.js +113 -28
  385. package/src/helpers/Blocks/Blocks.test.js +100 -0
  386. package/src/helpers/Content/Content.js +23 -0
  387. package/src/helpers/Content/Content.test.js +39 -0
  388. package/src/helpers/Extensions/withBlockSchemaEnhancer.jsx +4 -1
  389. package/src/helpers/FormValidation/FormValidation.test.js +31 -0
  390. package/src/helpers/FormValidation/validators.ts +52 -6
  391. package/src/helpers/I18n/I18n.test.ts +44 -0
  392. package/src/helpers/I18n/I18n.ts +31 -0
  393. package/src/helpers/Loadable/__mocks__/Loadable.jsx +7 -22
  394. package/src/helpers/MessageLabels/MessageLabels.js +5 -0
  395. package/src/helpers/Robots/Robots.js +1 -1
  396. package/src/helpers/Robots/Robots.test.js +34 -0
  397. package/src/helpers/Url/Url.js +1 -0
  398. package/src/helpers/Utils/Date.js +26 -1
  399. package/src/helpers/Utils/Date.test.js +237 -0
  400. package/src/helpers/Utils/Utils.jsx +17 -0
  401. package/src/helpers/Utils/Utils.test.jsx +39 -0
  402. package/src/helpers/Utils/withSaveAsDraft.jsx +33 -9
  403. package/src/helpers/index.js +1 -0
  404. package/src/hooks/user/useUser.js +1 -1
  405. package/src/internalChecks.test.ts +11 -0
  406. package/src/middleware/api.js +14 -5
  407. package/src/reducers/blockTypes/blockTypes.js +38 -0
  408. package/src/reducers/content/content.js +3 -18
  409. package/src/reducers/diff/diff.js +5 -1
  410. package/src/reducers/diff/diff.test.js +60 -4
  411. package/src/reducers/index.js +2 -0
  412. package/src/reducers/querystring/querystring.js +8 -1
  413. package/src/reducers/users/users.js +1 -1
  414. package/src/routes.js +10 -0
  415. package/src/server.jsx +14 -6
  416. package/src/start-client.jsx +21 -3
  417. package/test-addons-loader.js +3 -0
  418. package/test-setup-globals.js +56 -2
  419. package/theme/themes/default/elements/segment.variables +9 -16
  420. package/theme/themes/default/globals/site.variables +3 -3
  421. package/theme/themes/pastanaga/collections/form.overrides +22 -1
  422. package/theme/themes/pastanaga/elements/button.overrides +30 -3
  423. package/theme/themes/pastanaga/elements/segment.variables +1 -4
  424. package/theme/themes/pastanaga/extras/block-types.less +17 -0
  425. package/theme/themes/pastanaga/extras/contents.less +63 -4
  426. package/theme/themes/pastanaga/extras/main.less +16 -4
  427. package/theme/themes/pastanaga/extras/toolbar.less +10 -5
  428. package/theme/themes/pastanaga/extras/videoembed.less +22 -0
  429. package/theme/themes/pastanaga/extras/widgets.less +79 -0
  430. package/theme/themes/pastanaga/globals/site.variables +0 -3
  431. package/tsconfig.declarations.json +1 -1
  432. package/tsconfig.json +1 -1
  433. package/types/actions/blockTypes/blockTypes.d.ts +7 -0
  434. package/types/components/index.d.ts +1 -1
  435. package/types/components/manage/Blocks/Block/Order/Item.test.d.ts +1 -0
  436. package/types/components/manage/Blocks/Block/Order/utilities.d.ts +2 -1
  437. package/types/components/manage/Blocks/Grid/context.d.ts +1 -0
  438. package/types/components/manage/Blocks/Maps/Body.d.ts +9 -0
  439. package/types/components/manage/Blocks/Maps/View.d.ts +1 -1
  440. package/types/components/manage/Blocks/Teaser/utils.d.ts +5 -0
  441. package/types/components/manage/Blocks/Video/Body.d.ts +4 -2
  442. package/types/components/manage/Blocks/Video/schema.d.ts +4 -0
  443. package/types/components/manage/Contents/Contents.d.ts +1 -1
  444. package/types/components/manage/Contents/ContentsIndexHeader.d.ts +6 -11
  445. package/types/components/manage/Contents/ContentsItem.d.ts +3 -10
  446. package/types/components/manage/Contents/DropZoneContent.d.ts +2 -0
  447. package/types/components/manage/Contents/__mocks__/index.d.ts +2 -2
  448. package/types/components/manage/Controlpanels/BlockType.d.ts +7 -0
  449. package/types/components/manage/Controlpanels/BlockTypes.d.ts +7 -0
  450. package/types/components/manage/Controlpanels/ContentType.d.ts +2 -2
  451. package/types/components/manage/Controlpanels/Controlpanel.d.ts +2 -5
  452. package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
  453. package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
  454. package/types/components/manage/Controlpanels/VersionOverview.d.ts +2 -1
  455. package/types/components/manage/Controlpanels/index.d.ts +3 -2
  456. package/types/components/manage/Diff/Diff.d.ts +7 -2
  457. package/types/components/manage/Form/__mocks__/index.d.ts +8 -8
  458. package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
  459. package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
  460. package/types/components/manage/Sidebar/ObjectBrowserBody.test.d.ts +1 -0
  461. package/types/components/manage/Sidebar/SidebarPortal.d.ts +7 -15
  462. package/types/components/manage/Toolbar/Types.crash.test.d.ts +1 -0
  463. package/types/components/manage/Widgets/AlignWidget.d.ts +8 -10
  464. package/types/components/manage/Widgets/AlignWidget.stories.d.ts +1 -0
  465. package/types/components/manage/Widgets/BlockAlignment.d.ts +7 -0
  466. package/types/components/manage/Widgets/BlockAlignment.stories.d.ts +8 -0
  467. package/types/components/manage/Widgets/BlockWidth.d.ts +7 -0
  468. package/types/components/manage/Widgets/BlockWidth.stories.d.ts +6 -0
  469. package/types/components/manage/Widgets/ButtonsWidget.d.ts +48 -1
  470. package/types/components/manage/Widgets/ButtonsWidget.stories.d.ts +3 -0
  471. package/types/components/manage/Widgets/FormFieldWrapper.d.ts +28 -5
  472. package/types/components/manage/Widgets/ImageWidget.d.ts +1 -1
  473. package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
  474. package/types/components/manage/Widgets/ObjectBrowserWidget.d.ts +2 -0
  475. package/types/components/manage/Widgets/QueryWidget.d.ts +5 -2
  476. package/types/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.d.ts +22 -5
  477. package/types/components/manage/Widgets/SelectStyling.d.ts +1 -0
  478. package/types/components/manage/Widgets/Size.d.ts +7 -0
  479. package/types/components/manage/Widgets/Size.stories.d.ts +6 -0
  480. package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
  481. package/types/components/manage/Widgets/__mocks__/index.d.ts +33 -33
  482. package/types/components/manage/Widgets/index.d.ts +11 -6
  483. package/types/components/theme/ConnectionRefused/ConnectionRefused.d.ts +2 -2
  484. package/types/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.d.ts +3 -0
  485. package/types/components/theme/PasswordReset/PasswordReset.d.ts +6 -2
  486. package/types/components/theme/Search/Search.d.ts +1 -1
  487. package/types/components/theme/Sitemap/Sitemap.stories.d.ts +13 -0
  488. package/types/components/theme/SlotRenderer/SlotRenderer.d.ts +4 -5
  489. package/types/components/theme/Unauthorized/Unauthorized.d.ts +2 -2
  490. package/types/components/theme/VideoEmbed/VideoEmbed.d.ts +2 -0
  491. package/types/components/theme/View/EventView.stories.d.ts +19 -0
  492. package/types/components/theme/View/FileView.stories.d.ts +18 -0
  493. package/types/components/theme/View/LinkView.stories.d.ts +18 -0
  494. package/types/components/theme/View/ListingView.stories.d.ts +24 -0
  495. package/types/components/theme/View/NewsItemView.stories.d.ts +23 -0
  496. package/types/components/theme/View/RenderBlocks.stories.d.ts +23 -0
  497. package/types/components/theme/View/SummaryView.stories.d.ts +23 -0
  498. package/types/components/theme/View/TabularView.stories.d.ts +23 -0
  499. package/types/config/ControlPanels.d.ts +1 -0
  500. package/types/config/Views.d.ts +1 -1
  501. package/types/config/Widgets.d.ts +6 -0
  502. package/types/config/slots.d.ts +7 -0
  503. package/types/constants/ActionTypes.d.ts +1 -0
  504. package/types/helpers/Blocks/Blocks.d.ts +4 -0
  505. package/types/helpers/Content/Content.d.ts +7 -0
  506. package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +4 -5
  507. package/types/helpers/FormValidation/validators.d.ts +18 -1
  508. package/types/helpers/I18n/I18n.d.ts +20 -0
  509. package/types/helpers/Loadable/__mocks__/Loadable.d.ts +2 -2
  510. package/types/helpers/MessageLabels/MessageLabels.d.ts +100 -94
  511. package/types/helpers/Utils/Utils.d.ts +1 -0
  512. package/types/helpers/index.d.ts +1 -0
  513. package/types/reducers/blockTypes/blockTypes.d.ts +16 -0
  514. package/types/reducers/index.d.ts +2 -0
  515. package/types/routes.d.ts +7 -5
  516. package/vitest.config.mjs +84 -42
  517. package/webpack-plugins/webpack-less-plugin.js +1 -1
  518. package/webpack-plugins/webpack-scss-plugin.js +172 -0
  519. package/jest-addons-loader.js +0 -3
  520. package/jest-extender-plugin.js +0 -39
  521. package/jest-setup-afterenv.js +0 -2
  522. package/jest-svgsystem-transform.js +0 -10
  523. package/patches/patchit.sh +0 -2
  524. package/patches/razzle-jest.patch +0 -10
  525. package/src/components/manage/Contents/__mocks__/index.vitest.tsx +0 -5
  526. package/src/components/manage/Form/__mocks__/index.vitest.tsx +0 -73
  527. package/src/components/manage/Sidebar/SidebarPortal.jsx +0 -47
  528. package/src/components/manage/Sidebar/SidebarPortal.test.jsx +0 -26
  529. package/src/components/manage/Widgets/AlignWidget.test.jsx +0 -59
  530. package/src/components/manage/Widgets/ButtonsWidget.jsx +0 -41
  531. package/src/components/manage/Widgets/ButtonsWidget.test.jsx +0 -70
  532. package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +0 -41
  533. package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +0 -39
  534. package/test-setup-globals-vitest.js +0 -46
  535. package/theme/themes/pastanaga/extras/utils.less +0 -63
package/razzle.config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /* eslint no-console: 0 */
2
2
  const path = require('path');
3
- const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder');
3
+ const makeLoaderFinder = require('@plone/razzle-dev-utils/makeLoaderFinder');
4
4
  const nodeExternals = require('webpack-node-externals');
5
5
  const LoadablePlugin = require('@loadable/webpack-plugin');
6
6
  const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
@@ -15,7 +15,6 @@ const {
15
15
  const { AddonRegistry } = require('@plone/registry/addon-registry');
16
16
  const CircularDependencyPlugin = require('circular-dependency-plugin');
17
17
  const TerserPlugin = require('terser-webpack-plugin');
18
- const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
19
18
  const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
20
19
  const AfterBuildPlugin = require('@fiverr/afterbuild-webpack-plugin');
21
20
 
@@ -116,25 +115,11 @@ const defaultModify = ({
116
115
  },
117
116
  });
118
117
 
119
- // This is needed to override Razzle use of the unmaintained CleanCSS
120
- // which does not have support for recently CSS features (container queries).
121
- // Using the default provided (cssnano) by css-minimizer-webpack-plugin
122
- // should be enough see:
123
- // (https://github.com/clean-css/clean-css/discussions/1209)
118
+ // TODO: remove this before merging the Razzle fork into Volto 19
119
+ // @sneridagh: Tried to remove this now that we have forked Razzle
120
+ // but I cannot pinpoint where this comes from, and it seems undefined
121
+ // always.
124
122
  delete options.webpackOptions.terserPluginOptions?.sourceMap;
125
- if (!dev) {
126
- config.optimization = Object.assign({}, config.optimization, {
127
- minimizer: [
128
- new TerserPlugin(options.webpackOptions.terserPluginOptions),
129
- new CssMinimizerPlugin({
130
- sourceMap: options.razzleOptions.enableSourceMaps,
131
- minimizerOptions: {
132
- sourceMap: options.razzleOptions.enableSourceMaps,
133
- },
134
- }),
135
- ],
136
- });
137
- }
138
123
 
139
124
  config.plugins.unshift(
140
125
  // restrict moment.js locales to supported languages
@@ -310,6 +295,7 @@ const defaultModify = ({
310
295
  'load-volto-addons': addonsLoaderPath,
311
296
  ...registry.getResolveAliases(),
312
297
  '@plone/volto': `${registry.voltoPath}/src`,
298
+ '@plone/volto-slate': `${registry.voltoPath}/../volto-slate/src`,
313
299
  // to be able to reference path uncustomized by webpack
314
300
  '@plone/volto-original': `${registry.voltoPath}/src`,
315
301
  // be able to reference current package from customized package
@@ -436,11 +422,16 @@ const defaultModify = ({
436
422
  const addonExtenders = registry.getAddonExtenders().map((m) => require(m));
437
423
 
438
424
  const defaultPlugins = [
439
- { object: require('./webpack-plugins/webpack-less-plugin')({ registry }) },
440
- { object: require('./webpack-plugins/webpack-svg-plugin') },
441
- { object: require('./webpack-plugins/webpack-bundle-analyze-plugin') },
442
- { object: require('./jest-extender-plugin') },
443
- 'scss',
425
+ {
426
+ name: 'less',
427
+ object: require('./webpack-plugins/webpack-less-plugin')({ registry }),
428
+ },
429
+ { name: 'svg', object: require('./webpack-plugins/webpack-svg-plugin') },
430
+ {
431
+ name: 'bundle-analyze',
432
+ object: require('./webpack-plugins/webpack-bundle-analyze-plugin'),
433
+ },
434
+ { name: 'scss', object: require('./webpack-plugins/webpack-scss-plugin') },
444
435
  ];
445
436
 
446
437
  const plugins = addonExtenders.reduce(
@@ -0,0 +1,24 @@
1
+ import { GET_BLOCKTYPES_INDEX } from '@plone/volto/constants/ActionTypes';
2
+
3
+ export function getBlockTypes(
4
+ id: string | null = null,
5
+ path: string | null = null,
6
+ ) {
7
+ let requestPath = '/@blocktypes';
8
+
9
+ if (id) {
10
+ requestPath += `/${id}`;
11
+ }
12
+
13
+ if (id && path) {
14
+ requestPath += `?path=${path}`;
15
+ }
16
+
17
+ return {
18
+ type: GET_BLOCKTYPES_INDEX,
19
+ request: {
20
+ op: 'get',
21
+ path: requestPath,
22
+ },
23
+ };
24
+ }
@@ -12,7 +12,6 @@ import {
12
12
  SYSTEM_INFORMATION,
13
13
  DATABASE_INFORMATION,
14
14
  } from '@plone/volto/constants/ActionTypes';
15
- import { getSite } from '@plone/volto/actions/site/site';
16
15
 
17
16
  /**
18
17
  * Get controlpanel function.
@@ -88,17 +87,13 @@ export function listControlpanels() {
88
87
  * @returns {Object} Update controlpanel action.
89
88
  */
90
89
  export function updateControlpanel(url, data) {
91
- return (dispatch) => {
92
- dispatch({
93
- type: UPDATE_CONTROLPANEL,
94
- request: {
95
- op: 'patch',
96
- path: url,
97
- data,
98
- },
99
- }).then(() => {
100
- dispatch(getSite());
101
- });
90
+ return {
91
+ type: UPDATE_CONTROLPANEL,
92
+ request: {
93
+ op: 'patch',
94
+ path: url,
95
+ data,
96
+ },
102
97
  };
103
98
  }
104
99
 
@@ -36,10 +36,9 @@ describe('Controlpanels action', () => {
36
36
  const url = 'http://localhost';
37
37
  const data = 'Hello World!';
38
38
 
39
- const dispatch = vi.fn().mockResolvedValue();
40
- updateControlpanel(url, data)(dispatch);
39
+ const action = updateControlpanel(url, data);
41
40
 
42
- expect(dispatch).toHaveBeenCalledWith({
41
+ expect(action).toEqual({
43
42
  type: UPDATE_CONTROLPANEL,
44
43
  request: {
45
44
  op: 'patch',
@@ -8,11 +8,7 @@ import Actions from './Actions';
8
8
 
9
9
  const mockStore = configureStore();
10
10
 
11
- vi.mock('@plone/volto/components/manage/Contents', async () => {
12
- return await import(
13
- '@plone/volto/components/manage/Contents/__mocks__/index.vitest.tsx'
14
- );
15
- });
11
+ vi.mock('@plone/volto/components/manage/Contents');
16
12
 
17
13
  describe('Actions', () => {
18
14
  it('renders an actions component', () => {
@@ -195,7 +195,7 @@ class Add extends Component {
195
195
  erroMessage = this.props.intl.formatMessage(messages.someErrors);
196
196
  }
197
197
  } else {
198
- erroMessage = errorsList.error?.message || error;
198
+ erroMessage = errorsList?.error?.message || error;
199
199
  }
200
200
 
201
201
  this.setState({ error: error });
@@ -240,11 +240,13 @@ class Add extends Component {
240
240
  if (this.props.location?.state?.translationOf) {
241
241
  const language = this.props.location.state.languageFrom;
242
242
  const langFileName = toGettextLang(language);
243
- import(
244
- /* @vite-ignore */ '@root/../locales/' + langFileName + '.json'
245
- ).then((locale) => {
246
- this.props.changeLanguage(language, locale.default);
247
- });
243
+ import(/* @vite-ignore */ '@root/../locales/' + langFileName + '.json')
244
+ .then((locale) => {
245
+ this.props.changeLanguage(language, locale.default);
246
+ })
247
+ .catch(() => {
248
+ this.props.changeLanguage(language, {});
249
+ });
248
250
  this.props.history.push(this.props.location?.state?.translationOf);
249
251
  } else {
250
252
  this.props.history.push(getBaseUrl(this.props.pathname));
@@ -266,9 +268,9 @@ class Add extends Component {
266
268
  this.props.schema.properties,
267
269
  );
268
270
  const translationObject = this.props.location?.state?.translationObject;
269
-
270
271
  const translateTo = translationObject
271
- ? langmap?.[this.props.location?.state?.language]?.nativeName
272
+ ? langmap?.[this.props.location?.state?.language]?.nativeName ||
273
+ this.props.location?.state?.language
272
274
  : null;
273
275
 
274
276
  // Get initial blocks from local config, if any
@@ -480,9 +482,12 @@ class Add extends Component {
480
482
  <Grid.Column>
481
483
  <div className="new-translation">
482
484
  <Menu pointing secondary attached tabular>
483
- <Menu.Item name={translateTo.toUpperCase()} active={true}>
485
+ <Menu.Item
486
+ name={translateTo?.toUpperCase() || ''}
487
+ active={true}
488
+ >
484
489
  {`${this.props.intl.formatMessage(messages.translateTo, {
485
- lang: translateTo,
490
+ lang: translateTo || '',
486
491
  })}`}
487
492
  </Menu.Item>
488
493
  </Menu>
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
+ import { CookiesProvider } from 'react-cookie';
5
6
  import config from '@plone/volto/registry';
6
7
  import Add from './Add';
7
8
 
@@ -43,7 +44,9 @@ describe('Add', () => {
43
44
  });
44
45
  const { container } = render(
45
46
  <Provider store={store}>
46
- <Add location={{ pathname: '/blog', search: { type: 'Document' } }} />
47
+ <CookiesProvider>
48
+ <Add location={{ pathname: '/blog', search: { type: 'Document' } }} />
49
+ </CookiesProvider>
47
50
  </Provider>,
48
51
  );
49
52
  expect(container).toMatchSnapshot();
@@ -70,7 +73,9 @@ describe('Add', () => {
70
73
  });
71
74
  const { container } = render(
72
75
  <Provider store={store}>
73
- <Add location={{ pathname: '/blog', search: { type: 'Document' } }} />
76
+ <CookiesProvider>
77
+ <Add location={{ pathname: '/blog', search: { type: 'Document' } }} />
78
+ </CookiesProvider>
74
79
  </Provider>,
75
80
  );
76
81
 
@@ -109,7 +114,9 @@ describe('Add', () => {
109
114
  });
110
115
  const { container } = render(
111
116
  <Provider store={store}>
112
- <Add location={{ pathname: '/blog', search: { type: 'Document' } }} />
117
+ <CookiesProvider>
118
+ <Add location={{ pathname: '/blog', search: { type: 'Document' } }} />
119
+ </CookiesProvider>
113
120
  </Provider>,
114
121
  );
115
122
 
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
+ import { CookiesProvider } from 'react-cookie';
4
5
  import configureMockStore from 'redux-mock-store';
5
6
  import thunk from 'redux-thunk';
6
7
 
@@ -46,8 +47,10 @@ describe('Aliases', () => {
46
47
  });
47
48
  const { container } = render(
48
49
  <Provider store={store}>
49
- <Aliases location={{ pathname: '/blog/aliases' }} />
50
- <div id="toolbar"></div>
50
+ <CookiesProvider>
51
+ <Aliases location={{ pathname: '/blog/aliases' }} />
52
+ <div id="toolbar"></div>
53
+ </CookiesProvider>
51
54
  </Provider>,
52
55
  );
53
56
 
@@ -10,6 +10,7 @@ import { useIntl, defineMessages } from 'react-intl';
10
10
  import Icon from '@plone/volto/components/theme/Icon/Icon';
11
11
  import AnimateHeight from 'react-animate-height';
12
12
  import config from '@plone/volto/registry';
13
+ import { formatMessageWithFallback } from '@plone/volto/helpers/I18n/I18n';
13
14
  import upSVG from '@plone/volto/icons/up-key.svg';
14
15
  import downSVG from '@plone/volto/icons/down-key.svg';
15
16
  import BlockChooserSearch from './BlockChooserSearch';
@@ -98,25 +99,20 @@ const BlockChooser = ({
98
99
  }
99
100
  const [filterValue, setFilterValue] = React.useState('');
100
101
 
101
- const getFormatMessage = (message) =>
102
- intl.formatMessage({
103
- id: message,
104
- defaultMessage: message,
105
- });
106
-
107
102
  function blocksAvailableFilter(blocks) {
108
103
  return blocks.filter(
109
104
  (block) =>
110
- getFormatMessage(block.title)
105
+ formatMessageWithFallback(intl, block.title)
111
106
  .toLowerCase()
112
107
  .includes(filterValue.toLowerCase()) ||
108
+ block.title.toLowerCase().includes(filterValue.toLowerCase()) ||
113
109
  filterVariations(block)?.length,
114
110
  );
115
111
  }
116
112
  function filterVariations(block) {
117
113
  return block.variations?.filter(
118
114
  (variation) =>
119
- getFormatMessage(variation.title)
115
+ formatMessageWithFallback(intl, variation.title)
120
116
  .toLowerCase()
121
117
  .includes(filterValue.toLowerCase()) &&
122
118
  !variation.title.toLowerCase().includes('default'),
@@ -144,9 +140,11 @@ const BlockChooser = ({
144
140
  }}
145
141
  >
146
142
  <Icon name={block.icon} size="36px" />
147
- {getFormatMessage(block.title)}
143
+ {formatMessageWithFallback(intl, block.title)}
148
144
  {filterValue && variations?.[0]?.title && (
149
- <small>{getFormatMessage(variations[0].title)}</small>
145
+ <small>
146
+ {formatMessageWithFallback(intl, variations[0].title)}
147
+ </small>
150
148
  )}
151
149
  </Button>
152
150
  </Button.Group>
@@ -8,6 +8,7 @@ import {
8
8
  getBlocks,
9
9
  getBlocksFieldname,
10
10
  getBlocksLayoutFieldname,
11
+ getInvalidBlockLayoutIds,
11
12
  applyBlockDefaults,
12
13
  getBlocksHierarchy,
13
14
  addBlock,
@@ -260,16 +261,18 @@ const BlocksForm = (props) => {
260
261
  const editBlockWrapper = children || defaultBlockWrapper;
261
262
 
262
263
  // Remove invalid blocks on saving
263
- // Note they are alreaady filtered by DragDropList, but we also want them
264
+ // Note they are already filtered by DragDropList, but we also want them
264
265
  // to be removed when the user saves the page next. Otherwise the invalid
265
266
  // blocks would linger for ever.
266
-
267
- for (const [n, v] of blockList) {
268
- if (!v) {
269
- const newFormData = deleteBlock(properties, n, intl);
270
- onChangeFormData(newFormData);
267
+ useEffect(() => {
268
+ const invalidBlockIds = getInvalidBlockLayoutIds(properties);
269
+ if (invalidBlockIds.length === 0) return;
270
+ let newFormData = properties;
271
+ for (const id of invalidBlockIds) {
272
+ newFormData = deleteBlock(newFormData, id, intl);
271
273
  }
272
- }
274
+ onChangeFormData(newFormData);
275
+ }, [properties, intl, onChangeFormData]);
273
276
 
274
277
  useEvent('voltoClickBelowContent', () => {
275
278
  if (!config.experimental.addBlockButton.enabled || !isMainForm) return;
@@ -7,11 +7,7 @@ import config from '@plone/volto/registry';
7
7
 
8
8
  config.experimental = { addBlockButton: { enabled: false } };
9
9
 
10
- vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
11
- return await import(
12
- '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
13
- );
14
- });
10
+ vi.mock('@plone/volto/helpers/Loadable/Loadable');
15
11
 
16
12
  beforeAll(async () => {
17
13
  const { __setLoadables } = await import(
@@ -161,19 +157,12 @@ test('Removes invalid blocks on saving', () => {
161
157
  </Provider>,
162
158
  );
163
159
 
160
+ expect(onChangeFormData).toHaveBeenCalledTimes(1);
164
161
  expect(onChangeFormData).toHaveBeenCalledWith({
165
162
  blocks: {
166
163
  a: { '@type': 'custom', text: 'a' },
167
164
  b: { '@type': 'custom', text: 'b' },
168
165
  },
169
- blocks_layout: { items: ['a', 'b', 'MISSING-YOU-1'] },
170
- });
171
-
172
- expect(onChangeFormData).toHaveBeenCalledWith({
173
- blocks: {
174
- a: { '@type': 'custom', text: 'a' },
175
- b: { '@type': 'custom', text: 'b' },
176
- },
177
- blocks_layout: { items: ['a', 'b', 'MISSING-YOU-2'] },
166
+ blocks_layout: { items: ['a', 'b'] },
178
167
  });
179
168
  });
@@ -149,15 +149,6 @@ export class Edit extends Component {
149
149
  this.props.setUIState({ hovered: this.props.id });
150
150
  }
151
151
  }}
152
- onFocus={(e) => {
153
- // TODO: This `onFocus` steals somehow the focus from the slate block
154
- // we have to investigate why this is happening
155
- // Apparently, I can't see any difference in the behavior
156
- // If any, we can fix it in successive iterations
157
- // if (this.props.hovered !== this.props.id) {
158
- // this.props.setUIState({ hovered: this.props.id });
159
- // }
160
- }}
161
152
  onMouseLeave={(e) => {
162
153
  e.preventDefault();
163
154
  e.stopPropagation();
@@ -172,6 +163,24 @@ export class Edit extends Component {
172
163
  e,
173
164
  );
174
165
  }}
166
+ // onFocus={(e) => {
167
+ // // TODO: This `onFocus` steals somehow the focus from the slate block
168
+ // // we have to investigate why this is happening
169
+ // // Apparently, I can't see any difference in the behavior
170
+ // // If any, we can fix it in successive iterations
171
+ // // if (this.props.hovered !== this.props.id) {
172
+ // // this.props.setUIState({ hovered: this.props.id });
173
+ // // }
174
+ // }}
175
+ onFocus={(e) => {
176
+ const isMultipleSelection = e.shiftKey || e.ctrlKey || e.metaKey;
177
+ !this.props.selected &&
178
+ this.props.onSelectBlock(
179
+ this.props.id,
180
+ this.props.selected ? false : isMultipleSelection,
181
+ e,
182
+ );
183
+ }}
175
184
  onKeyDown={
176
185
  !(blockHasOwnFocusManagement || disableNewBlocks)
177
186
  ? (e) =>
@@ -218,6 +227,7 @@ export class Edit extends Component {
218
227
  e.stopPropagation();
219
228
  this.props.setUIState({ hovered: this.props.id });
220
229
  }}
230
+ // Mantenha apenas este onFocus ou remova se não for necessário
221
231
  onFocus={(e) => {
222
232
  e.preventDefault();
223
233
  e.stopPropagation();
@@ -245,7 +255,6 @@ export class Edit extends Component {
245
255
  className={cx(`block ${type}`, { selected: this.props.selected })}
246
256
  style={{ outline: 'none' }}
247
257
  ref={this.blockNode}
248
- // The tabIndex is required for the keyboard navigation
249
258
  tabIndex={-1}
250
259
  >
251
260
  {this.props.intl.formatMessage(messages.unknownBlock, {
@@ -5,7 +5,9 @@ import includes from 'lodash/includes';
5
5
  import cx from 'classnames';
6
6
  import Icon from '@plone/volto/components/theme/Icon/Icon';
7
7
  import { setUIState } from '@plone/volto/actions/form/form';
8
+ import { formatMessageWithFallback } from '@plone/volto/helpers/I18n/I18n';
8
9
  import config from '@plone/volto/registry';
10
+ import { useIntl } from 'react-intl';
9
11
 
10
12
  import deleteSVG from '@plone/volto/icons/delete.svg';
11
13
  import dragSVG from '@plone/volto/icons/drag.svg';
@@ -25,6 +27,7 @@ export const Item = forwardRef(
25
27
  onRemove,
26
28
  onSelectBlock,
27
29
  parentId,
30
+ parentType,
28
31
  style,
29
32
  value,
30
33
  wrapperRef,
@@ -33,12 +36,27 @@ export const Item = forwardRef(
33
36
  },
34
37
  ref,
35
38
  ) => {
39
+ const intl = useIntl();
36
40
  const selected = useSelector((state) => state.form.ui.selected);
37
41
  const hovered = useSelector((state) => state.form.ui.hovered);
38
42
  const multiSelected = useSelector((state) => state.form.ui.multiSelected);
39
43
  const gridSelected = useSelector((state) => state.form.ui.gridSelected);
40
44
  const dispatch = useDispatch();
41
45
 
46
+ const icon =
47
+ config.blocks.blocksConfig[data?.['@type']]?.icon ||
48
+ config.blocks.blocksConfig.title?.icon;
49
+
50
+ const required =
51
+ typeof data?.required === 'boolean'
52
+ ? data.required
53
+ : includes(config.blocks.requiredBlocks, data?.['@type']);
54
+ const fixed = !!data?.fixed;
55
+ const configTitle = config.blocks.blocksConfig[data?.['@type']]?.title;
56
+ const blockTitle =
57
+ data?.plaintext ||
58
+ formatMessageWithFallback(intl, configTitle) ||
59
+ data?.title;
42
60
  return (
43
61
  <li
44
62
  className={classNames(
@@ -88,31 +106,32 @@ export const Item = forwardRef(
88
106
  ref={ref}
89
107
  style={style}
90
108
  >
91
- <button
92
- ref={ref}
93
- {...handleProps}
94
- className={classNames('action', 'drag')}
95
- tabIndex={0}
96
- data-cypress="draggable-handle"
97
- >
98
- <Icon name={dragSVG} size="16px" />
99
- </button>
109
+ {!fixed && (
110
+ <button
111
+ ref={ref}
112
+ {...handleProps}
113
+ className={classNames('action', 'drag')}
114
+ tabIndex={0}
115
+ data-cypress="draggable-handle"
116
+ >
117
+ <Icon name={dragSVG} size="16px" />
118
+ </button>
119
+ )}
100
120
  <span
101
121
  className={cx('text', {
102
122
  errored: errors && Object.keys(errors).length > 0,
103
123
  })}
104
124
  >
105
- {config.blocks.blocksConfig[data?.['@type']]?.icon && (
125
+ {icon && (
106
126
  <Icon
107
- name={config.blocks.blocksConfig[data?.['@type']]?.icon}
127
+ name={icon}
108
128
  size="20px"
109
129
  style={{ verticalAlign: 'middle' }}
110
130
  />
111
131
  )}{' '}
112
- {data?.plaintext ||
113
- config.blocks.blocksConfig[data?.['@type']]?.title}
132
+ {blockTitle}
114
133
  </span>
115
- {!clone && onRemove && (
134
+ {!clone && onRemove && !required && (
116
135
  <button
117
136
  onClick={onRemove}
118
137
  className={classNames('action', 'delete')}
@@ -0,0 +1,90 @@
1
+ import React from 'react';
2
+ import configureStore from 'redux-mock-store';
3
+ import { Provider } from 'react-intl-redux';
4
+ import { render } from '@testing-library/react';
5
+ import config from '@plone/volto/registry';
6
+
7
+ import { Item } from './Item';
8
+
9
+ const mockStore = configureStore();
10
+
11
+ const defaultStoreState = {
12
+ intl: {
13
+ locale: 'en',
14
+ messages: {},
15
+ },
16
+ form: {
17
+ ui: {
18
+ selected: null,
19
+ hovered: null,
20
+ multiSelected: [],
21
+ gridSelected: null,
22
+ },
23
+ },
24
+ };
25
+
26
+ const renderItem = (data = {}) => {
27
+ const store = mockStore(defaultStoreState);
28
+
29
+ return render(
30
+ <Provider store={store}>
31
+ <Item
32
+ id="title-block-id"
33
+ data={{ '@type': 'title', ...data }}
34
+ depth={0}
35
+ indentationWidth={25}
36
+ onRemove={() => {}}
37
+ onSelectBlock={() => {}}
38
+ handleProps={{}}
39
+ />
40
+ </Provider>,
41
+ );
42
+ };
43
+
44
+ describe('Order Item', () => {
45
+ let requiredBlocks;
46
+
47
+ beforeEach(() => {
48
+ requiredBlocks = [...(config.blocks.requiredBlocks || [])];
49
+ config.blocks.requiredBlocks = [];
50
+ });
51
+
52
+ afterEach(() => {
53
+ config.blocks.requiredBlocks = requiredBlocks;
54
+ });
55
+
56
+ test('renders drag and delete actions for movable and removable blocks', () => {
57
+ const { container } = renderItem();
58
+
59
+ expect(container.querySelector('.action.drag')).not.toBeNull();
60
+ expect(container.querySelector('.action.delete')).not.toBeNull();
61
+ });
62
+
63
+ test('hides delete action for required blocks', () => {
64
+ const { container } = renderItem({ required: true });
65
+
66
+ expect(container.querySelector('.action.delete')).toBeNull();
67
+ });
68
+
69
+ test('hides delete action for block types configured as required', () => {
70
+ config.blocks.requiredBlocks = ['title'];
71
+
72
+ const { container } = renderItem();
73
+
74
+ expect(container.querySelector('.action.delete')).toBeNull();
75
+ });
76
+
77
+ test('allows explicit required=false to override required block types', () => {
78
+ config.blocks.requiredBlocks = ['title'];
79
+
80
+ const { container } = renderItem({ required: false });
81
+
82
+ expect(container.querySelector('.action.delete')).not.toBeNull();
83
+ });
84
+
85
+ test('hides drag action for fixed blocks', () => {
86
+ const { container } = renderItem({ fixed: true });
87
+
88
+ expect(container.querySelector('.action.drag')).toBeNull();
89
+ });
90
+ });