@plone/volto 19.0.0-alpha.0 → 19.0.0-alpha.10

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 (367) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +37 -0
  3. package/CHANGELOG.md +274 -2
  4. package/README.md +3 -6
  5. package/cypress/docker/prefixed-rules.yml +26 -0
  6. package/cypress/docker/prefixed.yml +24 -0
  7. package/cypress/support/commands.js +12 -6
  8. package/cypress/support/guillotina.js +1 -0
  9. package/cypress.config.js +1 -0
  10. package/locales/af.json +1 -0
  11. package/locales/ar.json +1 -0
  12. package/locales/bg.json +1 -0
  13. package/locales/bn.json +1 -0
  14. package/locales/ca/LC_MESSAGES/volto.po +96 -17
  15. package/locales/ca.json +1 -1
  16. package/locales/cs.json +1 -0
  17. package/locales/cy.json +1 -0
  18. package/locales/da.json +1 -0
  19. package/locales/de/LC_MESSAGES/volto.po +104 -25
  20. package/locales/de.json +1 -1
  21. package/locales/el.json +1 -0
  22. package/locales/en/LC_MESSAGES/volto.po +97 -18
  23. package/locales/en.json +1 -1
  24. package/locales/en_AU.json +1 -0
  25. package/locales/en_GB.json +1 -0
  26. package/locales/eo.json +1 -0
  27. package/locales/es/LC_MESSAGES/volto.po +97 -18
  28. package/locales/es.json +1 -1
  29. package/locales/et.json +1 -0
  30. package/locales/eu/LC_MESSAGES/volto.po +96 -17
  31. package/locales/eu.json +1 -1
  32. package/locales/fa.json +1 -0
  33. package/locales/fi/LC_MESSAGES/volto.po +96 -17
  34. package/locales/fi.json +1 -1
  35. package/locales/fr/LC_MESSAGES/volto.po +97 -18
  36. package/locales/fr.json +1 -1
  37. package/locales/fu.json +1 -0
  38. package/locales/gl.json +1 -0
  39. package/locales/he.json +1 -0
  40. package/locales/hi/LC_MESSAGES/volto.po +100 -21
  41. package/locales/hi.json +1 -1
  42. package/locales/hr.json +1 -0
  43. package/locales/hu.json +1 -0
  44. package/locales/hy.json +1 -0
  45. package/locales/id.json +1 -0
  46. package/locales/it/LC_MESSAGES/volto.po +101 -22
  47. package/locales/it.json +1 -1
  48. package/locales/ja/LC_MESSAGES/volto.po +96 -17
  49. package/locales/ja.json +1 -1
  50. package/locales/ka.json +1 -0
  51. package/locales/kn.json +1 -0
  52. package/locales/ko.json +1 -0
  53. package/locales/lt.json +1 -0
  54. package/locales/lv.json +1 -0
  55. package/locales/mi.json +1 -0
  56. package/locales/mk.json +1 -0
  57. package/locales/my.json +1 -0
  58. package/locales/nb_NO.json +1 -0
  59. package/locales/nl/LC_MESSAGES/volto.po +100 -21
  60. package/locales/nl.json +1 -1
  61. package/locales/nn.json +1 -0
  62. package/locales/pl.json +1 -0
  63. package/locales/pt/LC_MESSAGES/volto.po +96 -17
  64. package/locales/pt.json +1 -1
  65. package/locales/pt_BR/LC_MESSAGES/volto.po +116 -37
  66. package/locales/pt_BR.json +1 -1
  67. package/locales/rm.json +1 -0
  68. package/locales/ro/LC_MESSAGES/volto.po +100 -21
  69. package/locales/ro.json +1 -1
  70. package/locales/ru/LC_MESSAGES/volto.po +100 -21
  71. package/locales/ru.json +1 -1
  72. package/locales/sk.json +1 -0
  73. package/locales/sl.json +1 -0
  74. package/locales/sm.json +1 -0
  75. package/locales/sq.json +1 -0
  76. package/locales/sr.json +1 -0
  77. package/locales/sr@cyrl.json +1 -0
  78. package/locales/sr@latn.json +1 -0
  79. package/locales/sv.json +1 -1
  80. package/locales/ta.json +1 -0
  81. package/locales/te.json +1 -0
  82. package/locales/th.json +1 -0
  83. package/locales/to.json +1 -0
  84. package/locales/tr.json +1 -0
  85. package/locales/uk.json +1 -0
  86. package/locales/vi.json +1 -0
  87. package/locales/volto.pot +97 -18
  88. package/locales/zh_CN/LC_MESSAGES/volto.po +96 -17
  89. package/locales/zh_CN.json +1 -1
  90. package/locales/zh_Hant.json +1 -0
  91. package/locales/zh_Hant_HK.json +1 -0
  92. package/package.json +36 -27
  93. package/razzle.config.js +16 -0
  94. package/src/actions/actions/actions.test.js +3 -3
  95. package/src/actions/addons/addons.test.js +15 -12
  96. package/src/actions/aliases/aliases.test.js +1 -1
  97. package/src/actions/content/content.js +0 -1
  98. package/src/actions/controlpanels/controlpanels.js +13 -7
  99. package/src/actions/controlpanels/controlpanels.test.js +11 -5
  100. package/src/actions/querystring/querystring.test.js +2 -2
  101. package/src/actions/types/types.test.js +1 -1
  102. package/src/actions/users/users.js +2 -2
  103. package/src/components/manage/Actions/Actions.test.jsx +5 -1
  104. package/src/components/manage/Add/Add.jsx +27 -26
  105. package/src/components/manage/Add/Add.test.jsx +6 -3
  106. package/src/components/manage/Aliases/Aliases.test.jsx +7 -7
  107. package/src/components/manage/Blocks/Block/BlocksForm.jsx +1 -0
  108. package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +48 -16
  109. package/src/components/manage/Blocks/Block/Edit.jsx +3 -1
  110. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +9 -4
  111. package/src/components/manage/Blocks/Block/Settings.test.jsx +5 -1
  112. package/src/components/manage/Blocks/Block/StyleWrapper.jsx +11 -3
  113. package/src/components/manage/Blocks/Description/View.test.jsx +1 -1
  114. package/src/components/manage/Blocks/HTML/Edit.test.jsx +12 -5
  115. package/src/components/manage/Blocks/HTML/View.test.jsx +1 -1
  116. package/src/components/manage/Blocks/Image/Edit.jsx +5 -1
  117. package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +6 -2
  118. package/src/components/manage/Blocks/LeadImage/Edit.jsx +2 -2
  119. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +1 -1
  120. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -1
  121. package/src/components/manage/Blocks/Listing/ImageGallery.jsx +6 -4
  122. package/src/components/manage/Blocks/Listing/View.test.jsx +3 -1
  123. package/src/components/manage/Blocks/Maps/Edit.jsx +2 -1
  124. package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +5 -1
  125. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +21 -4
  126. package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +13 -7
  127. package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +12 -6
  128. package/src/components/manage/Blocks/Teaser/Data.jsx +21 -7
  129. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +1 -1
  130. package/src/components/manage/Blocks/Teaser/schema.js +8 -3
  131. package/src/components/manage/Blocks/Title/Edit.jsx +8 -2
  132. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +11 -1
  133. package/src/components/manage/Blocks/Video/Edit.jsx +2 -1
  134. package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +5 -1
  135. package/src/components/manage/ConditionalLink/ConditionalLink.test.tsx +109 -0
  136. package/src/components/manage/ConditionalLink/ConditionalLink.tsx +36 -0
  137. package/src/components/manage/Contents/Contents.jsx +23 -2
  138. package/src/components/manage/Contents/Contents.test.jsx +36 -13
  139. package/src/components/manage/Contents/ContentsBreadcrumbs.Multilingual.test.jsx +18 -5
  140. package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +20 -26
  141. package/src/components/manage/Contents/ContentsBreadcrumbs.test.jsx +14 -0
  142. package/src/components/manage/Contents/ContentsDeleteModal.jsx +258 -206
  143. package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +26 -8
  144. package/src/components/manage/Contents/ContentsItem.jsx +10 -2
  145. package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +5 -1
  146. package/src/components/manage/Contents/ContentsRenameModal.test.jsx +5 -1
  147. package/src/components/manage/Contents/ContentsTagsModal.test.jsx +5 -1
  148. package/src/components/manage/Contents/ContentsUploadModal.test.jsx +13 -22
  149. package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +5 -1
  150. package/src/components/manage/Contents/__mocks__/index.tsx +16 -0
  151. package/src/components/manage/Contents/__mocks__/index.vitest.tsx +5 -0
  152. package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +28 -3
  153. package/src/components/manage/Controlpanels/Aliases.test.jsx +35 -3
  154. package/src/components/manage/Controlpanels/ContentType.jsx +1 -1
  155. package/src/components/manage/Controlpanels/ContentType.test.jsx +29 -3
  156. package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +4 -2
  157. package/src/components/manage/Controlpanels/ContentTypes.test.jsx +25 -2
  158. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +37 -6
  159. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +47 -3
  160. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +3 -2
  161. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +15 -9
  162. package/src/components/manage/Controlpanels/ModerateComments.test.jsx +31 -5
  163. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +13 -4
  164. package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -5
  165. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +12 -4
  166. package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -3
  167. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +33 -4
  168. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +156 -175
  169. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +3 -1
  170. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +575 -630
  171. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +16 -9
  172. package/src/components/manage/Delete/Delete.test.jsx +45 -4
  173. package/src/components/manage/Diff/Diff.test.jsx +15 -6
  174. package/src/components/manage/Diff/DiffField.test.jsx +12 -6
  175. package/src/components/manage/Display/Display.test.jsx +17 -6
  176. package/src/components/manage/Edit/Edit.jsx +2 -3
  177. package/src/components/manage/Edit/Edit.test.jsx +11 -3
  178. package/src/components/manage/Form/BlockDataForm.test.jsx +5 -1
  179. package/src/components/manage/Form/Form.jsx +32 -0
  180. package/src/components/manage/Form/Form.test.jsx +27 -19
  181. package/src/components/manage/Form/InlineForm.jsx +2 -2
  182. package/src/components/manage/Form/InlineForm.test.jsx +5 -1
  183. package/src/components/manage/Form/ModalForm.test.jsx +5 -1
  184. package/src/components/manage/Form/__mocks__/index.tsx +17 -0
  185. package/src/components/manage/Form/__mocks__/index.vitest.tsx +73 -0
  186. package/src/components/manage/History/History.test.jsx +3 -1
  187. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +6 -4
  188. package/src/components/manage/MaybeWrap/MaybeWrap.tsx +15 -0
  189. package/src/components/manage/Multilingual/CompareLanguages.jsx +2 -5
  190. package/src/components/manage/Multilingual/CreateTranslation.jsx +8 -8
  191. package/src/components/manage/Multilingual/ManageTranslations.jsx +4 -2
  192. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +8 -3
  193. package/src/components/manage/Multilingual/TranslationObject.jsx +1 -1
  194. package/src/components/manage/Preferences/ChangePassword.test.jsx +9 -2
  195. package/src/components/manage/Preferences/PersonalInformation.test.jsx +3 -1
  196. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +20 -7
  197. package/src/components/manage/Rules/Rules.test.jsx +6 -3
  198. package/src/components/manage/Sharing/Sharing.test.jsx +3 -1
  199. package/src/components/manage/Sidebar/ObjectBrowserNav.jsx +2 -1
  200. package/src/components/manage/Sidebar/ObjectBrowserNav.test.jsx +3 -3
  201. package/src/components/manage/Sidebar/SidebarPortal.test.tsx +42 -0
  202. package/src/components/manage/Sidebar/SidebarPortal.tsx +48 -0
  203. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +2 -1
  204. package/src/components/manage/Toolbar/More.jsx +4 -1
  205. package/src/components/manage/Toolbar/More.test.jsx +9 -7
  206. package/src/components/manage/Toolbar/PersonalTools.jsx +2 -1
  207. package/src/components/manage/Toolbar/Toolbar.jsx +3 -4
  208. package/src/components/manage/Toolbar/Types.jsx +7 -7
  209. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +196 -14
  210. package/src/components/manage/UniversalLink/UniversalLink.tsx +215 -0
  211. package/src/components/manage/Widgets/ArrayWidget.test.jsx +22 -5
  212. package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +12 -5
  213. package/src/components/manage/Widgets/DatetimeWidget.jsx +5 -0
  214. package/src/components/manage/Widgets/DatetimeWidget.test.jsx +21 -6
  215. package/src/components/manage/Widgets/FileWidget.jsx +14 -8
  216. package/src/components/manage/Widgets/ImageWidget.jsx +176 -40
  217. package/src/components/manage/Widgets/InternalUrlWidget.jsx +2 -0
  218. package/src/components/manage/Widgets/NumberWidget.test.jsx +8 -7
  219. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +3 -0
  220. package/src/components/manage/Widgets/ObjectListWidget.jsx +11 -1
  221. package/src/components/manage/Widgets/ObjectListWidget.test.jsx +18 -8
  222. package/src/components/manage/Widgets/ObjectWidget.test.jsx +5 -1
  223. package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +12 -5
  224. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +12 -6
  225. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +44 -41
  226. package/src/components/manage/Widgets/SchemaWidget.test.jsx +12 -5
  227. package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +12 -5
  228. package/src/components/manage/Widgets/SelectAutoComplete.jsx +29 -12
  229. package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +12 -6
  230. package/src/components/manage/Widgets/SelectWidget.jsx +3 -1
  231. package/src/components/manage/Widgets/SelectWidget.test.jsx +12 -6
  232. package/src/components/manage/Widgets/TimeWidget.test.jsx +13 -5
  233. package/src/components/manage/Widgets/TokenWidget.test.jsx +12 -6
  234. package/src/components/manage/Widgets/UrlWidget.jsx +2 -0
  235. package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +18 -9
  236. package/src/components/manage/Widgets/__mocks__/index.tsx +16 -0
  237. package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +41 -0
  238. package/src/components/manage/Workflow/Workflow.test.jsx +17 -7
  239. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -3
  240. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +0 -4
  241. package/src/components/theme/App/App.jsx +3 -1
  242. package/src/components/theme/App/App.test.jsx +22 -17
  243. package/src/components/theme/AppExtras/AppExtras.test.jsx +6 -6
  244. package/src/components/theme/Avatar/Avatar.jsx +2 -1
  245. package/src/components/theme/Comments/CommentEditModal.test.jsx +5 -1
  246. package/src/components/theme/Comments/Comments.test.jsx +29 -12
  247. package/src/components/theme/ContactForm/ContactForm.test.jsx +8 -4
  248. package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +20 -2
  249. package/src/components/theme/Header/Header.test.jsx +19 -13
  250. package/src/components/theme/Image/Image.jsx +11 -8
  251. package/src/components/theme/LanguageSelector/{LanguageSelector.test.jsx → LanguageSelector.test.tsx} +6 -6
  252. package/src/components/theme/LanguageSelector/LanguageSelector.tsx +89 -0
  253. package/src/components/theme/Logo/Logo.Multilingual.test.jsx +0 -5
  254. package/src/components/theme/Logout/Logout.test.jsx +1 -1
  255. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +8 -12
  256. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +3 -5
  257. package/src/components/theme/Navigation/NavItem.jsx +1 -5
  258. package/src/components/theme/Navigation/Navigation.Multilingual.test.jsx +0 -5
  259. package/src/components/theme/NotFound/NotFound.jsx +5 -2
  260. package/src/components/theme/NotFound/NotFound.test.jsx +3 -0
  261. package/src/components/theme/PasswordReset/PasswordReset.test.jsx +10 -1
  262. package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +5 -1
  263. package/src/components/theme/PreviewImage/PreviewImage.jsx +1 -1
  264. package/src/components/theme/Register/Register.test.jsx +5 -1
  265. package/src/components/theme/RequestTimeout/RequestTimeout.jsx +1 -1
  266. package/src/components/theme/Search/Search.test.jsx +6 -4
  267. package/src/components/theme/Sitemap/Sitemap.jsx +6 -5
  268. package/src/components/theme/Sitemap/Sitemap.test.jsx +0 -1
  269. package/src/components/theme/TsTest/TsTest.test.tsx +0 -1
  270. package/src/components/theme/View/EventDatesInfo.test.jsx +12 -5
  271. package/src/components/theme/View/EventView.test.jsx +12 -5
  272. package/src/components/theme/View/FileView.jsx +9 -1
  273. package/src/components/theme/View/ListingView.test.jsx +2 -0
  274. package/src/components/theme/View/SummaryView.test.jsx +10 -0
  275. package/src/components/theme/View/TabularView.test.jsx +1 -0
  276. package/src/components/theme/View/View.jsx +1 -1
  277. package/src/components/theme/View/View.test.jsx +42 -23
  278. package/src/components/theme/Widgets/ImageWidget.jsx +2 -1
  279. package/src/config/ControlPanels.js +1 -0
  280. package/src/config/index.js +18 -25
  281. package/src/config/server.js +0 -2
  282. package/src/express-middleware/devproxy.js +20 -5
  283. package/src/helpers/Api/APIResourceWithAuth.js +8 -3
  284. package/src/helpers/Api/Api.js +7 -4
  285. package/src/helpers/Api/Api.plone.rest.test.js +11 -9
  286. package/src/helpers/Api/Api.test.js +11 -14
  287. package/src/helpers/AsyncConnect/AsyncConnect.test.jsx +145 -189
  288. package/src/helpers/AsyncConnect/ssr.js +4 -1
  289. package/src/helpers/AuthToken/AuthToken.test.js +60 -22
  290. package/src/helpers/Blocks/Blocks.test.js +1 -1
  291. package/src/helpers/Content/Content.js +23 -0
  292. package/src/helpers/Content/Content.test.js +39 -0
  293. package/src/helpers/Content/withClientSideContent.jsx +35 -0
  294. package/src/helpers/Extensions/withBlockSchemaEnhancer.jsx +4 -1
  295. package/src/helpers/Html/Html.jsx +13 -7
  296. package/src/helpers/Html/Html.test.jsx +32 -28
  297. package/src/helpers/LanguageMap/LanguageMap.js +115 -8
  298. package/src/helpers/Loadable/__mocks__/Loadable.jsx +16 -1
  299. package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +39 -0
  300. package/src/helpers/MessageLabels/MessageLabels.js +5 -0
  301. package/src/helpers/Sitemap/Sitemap.js +4 -4
  302. package/src/helpers/Url/Url.js +32 -2
  303. package/src/helpers/Url/Url.test.js +62 -0
  304. package/src/helpers/Utils/withSaveAsDraft.jsx +241 -0
  305. package/src/hooks/user/useUser.js +1 -1
  306. package/src/middleware/Api.test.js +51 -0
  307. package/src/middleware/api.js +78 -29
  308. package/src/middleware/storeProtectLoadUtils.test.js +93 -81
  309. package/src/reducers/content/content.js +3 -18
  310. package/src/reducers/diff/diff.js +5 -1
  311. package/src/reducers/diff/diff.test.js +60 -4
  312. package/src/routes.js +4 -2
  313. package/src/server.jsx +45 -14
  314. package/src/start-client.jsx +9 -6
  315. package/src/start-server.js +9 -3
  316. package/test-setup-config.jsx +0 -2
  317. package/test-setup-globals-vitest.js +46 -0
  318. package/theme/themes/pastanaga/collections/table.overrides +9 -0
  319. package/theme/themes/pastanaga/extras/blocks.less +26 -0
  320. package/theme/themes/pastanaga/extras/contents.less +17 -5
  321. package/theme/themes/pastanaga/extras/main.less +32 -2
  322. package/tsconfig.declarations.json +12 -1
  323. package/tsconfig.json +5 -5
  324. package/types/components/manage/Blocks/Teaser/schema.d.ts +1 -0
  325. package/types/components/manage/ConditionalLink/ConditionalLink.d.ts +11 -15
  326. package/types/components/manage/Contents/__mocks__/index.vitest.d.ts +2 -0
  327. package/types/components/manage/Controlpanels/Users/RenderUsers.d.ts +18 -2
  328. package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +6 -2
  329. package/types/components/manage/Controlpanels/index.d.ts +2 -2
  330. package/types/components/manage/Form/__mocks__/index.vitest.d.ts +8 -0
  331. package/types/components/manage/MaybeWrap/MaybeWrap.d.ts +7 -5
  332. package/types/components/manage/Sidebar/SidebarPortal.d.ts +7 -15
  333. package/types/components/manage/UniversalLink/UniversalLink.d.ts +54 -20
  334. package/types/components/manage/Widgets/ImageWidget.d.ts +41 -1
  335. package/types/components/manage/Widgets/RecurrenceWidget/Utils.d.ts +12 -18
  336. package/types/components/manage/Widgets/__mocks__/index.vitest.d.ts +33 -0
  337. package/types/components/theme/FormattedDate/FormattedDate.stories.d.ts +1 -1
  338. package/types/components/theme/LanguageSelector/LanguageSelector.d.ts +3 -10
  339. package/types/helpers/Content/Content.d.ts +7 -0
  340. package/types/helpers/Content/withClientSideContent.d.ts +1 -0
  341. package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +4 -5
  342. package/types/helpers/Helmet/Helmet.d.ts +1 -1
  343. package/types/helpers/LanguageMap/LanguageMap.d.ts +428 -4
  344. package/types/helpers/Loadable/__mocks__/Loadable.vitest.d.ts +3 -0
  345. package/types/helpers/MessageLabels/MessageLabels.d.ts +68 -62
  346. package/types/helpers/Url/Url.d.ts +14 -0
  347. package/types/helpers/Url/bulkFlattenToAppURL.d.ts +5 -0
  348. package/types/helpers/Utils/withSaveAsDraft.d.ts +1 -0
  349. package/types/middleware/api.d.ts +6 -9
  350. package/types/react-router-hash-link.d.ts +12 -0
  351. package/types/reducers/index.d.ts +1 -0
  352. package/types/routes.d.ts +4 -0
  353. package/types/server.d.ts +1 -1
  354. package/types/start-client.d.ts +0 -1
  355. package/vite-plugins/svg.mjs +81 -0
  356. package/vitest.config.mjs +77 -0
  357. package/package-why.json +0 -34
  358. package/src/actions/content/content.multilingual.test.js +0 -17
  359. package/src/components/manage/ConditionalLink/ConditionalLink.jsx +0 -27
  360. package/src/components/manage/ConditionalLink/ConditionalLink.test.jsx +0 -30
  361. package/src/components/manage/MaybeWrap/MaybeWrap.jsx +0 -9
  362. package/src/components/manage/Sidebar/SidebarPortal.jsx +0 -47
  363. package/src/components/manage/Sidebar/SidebarPortal.test.jsx +0 -26
  364. package/src/components/manage/UniversalLink/UniversalLink.jsx +0 -154
  365. package/src/components/manage/Widgets/FileWidget.test.jsx +0 -91
  366. package/src/components/theme/LanguageSelector/LanguageSelector.jsx +0 -77
  367. package/theme/themes/pastanaga/extras/utils.less +0 -63
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { Button, Dimmer, Loader, Message } from 'semantic-ui-react';
3
3
  import { useIntl, defineMessages } from 'react-intl';
4
- import { useDispatch } from 'react-redux';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
5
  import { useLocation } from 'react-router-dom';
6
6
  import loadable from '@loadable/component';
7
7
  import { connect } from 'react-redux';
@@ -9,11 +9,15 @@ import { compose } from 'redux';
9
9
  import { toast } from 'react-toastify';
10
10
  import useLinkEditor from '@plone/volto/components/manage/AnchorPlugin/useLinkEditor';
11
11
  import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
12
+ import config from '@plone/volto/registry';
12
13
 
13
14
  import {
14
15
  flattenToAppURL,
15
16
  getBaseUrl,
17
+ getParentUrl,
16
18
  isInternalURL,
19
+ normalizeUrl,
20
+ removeProtocol,
17
21
  } from '@plone/volto/helpers/Url/Url';
18
22
  import { validateFileUploadSize } from '@plone/volto/helpers/FormValidation/FormValidation';
19
23
  import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious';
@@ -28,6 +32,9 @@ import clearSVG from '@plone/volto/icons/clear.svg';
28
32
  import navTreeSVG from '@plone/volto/icons/nav.svg';
29
33
  import linkSVG from '@plone/volto/icons/link.svg';
30
34
  import uploadSVG from '@plone/volto/icons/upload.svg';
35
+ import Image from '../../theme/Image/Image';
36
+ import { urlValidator } from '@plone/volto/helpers/FormValidation/validators';
37
+ import { searchContent } from '@plone/volto/actions/search/search';
31
38
 
32
39
  const Dropzone = loadable(() => import('react-dropzone'));
33
40
 
@@ -70,6 +77,14 @@ const messages = defineMessages({
70
77
  id: 'imageUploadErrorMessage',
71
78
  defaultMessage: 'Please upload an image instead.',
72
79
  },
80
+ externalURLsNotAllowed: {
81
+ id: 'externalURLsNotAllowed',
82
+ defaultMessage: 'External URLs are not allowed in this field.',
83
+ },
84
+ internalImageNotFoundErrorMessage: {
85
+ id: 'internalImageNotFoundErrorMessage',
86
+ defaultMessage: 'No image was found in the internal path you provided.',
87
+ },
73
88
  });
74
89
 
75
90
  const UnconnectedImageInput = (props) => {
@@ -89,12 +104,15 @@ const UnconnectedImageInput = (props) => {
89
104
  placeholderLinkInput = '',
90
105
  onSelectItem,
91
106
  } = props;
92
- const imageValue = value?.[0]?.['@id'] || value;
107
+ const imageValue = value?.[0]?.['@id'] || value?.['@id'] || value;
93
108
 
94
109
  const intl = useIntl();
95
110
  const linkEditor = useLinkEditor();
96
111
  const location = useLocation();
97
112
  const dispatch = useDispatch();
113
+ const isFolderish = useSelector(
114
+ (state) => state?.content?.data?.is_folderish,
115
+ );
98
116
  const contextUrl = location.pathname;
99
117
 
100
118
  const [uploading, setUploading] = React.useState(false);
@@ -109,21 +127,41 @@ const UnconnectedImageInput = (props) => {
109
127
  const imageId = content?.['@id'];
110
128
  const image = content?.image;
111
129
  let loading = false;
130
+ const isRelationChoice = props.factory === 'Relation Choice';
112
131
 
113
132
  useEffect(() => {
114
133
  if (uploading && loading && loaded) {
115
134
  setUploading(false);
116
- onChange(id, imageId, {
117
- image_field: 'image',
118
- image_scales: { image: [image] },
119
- });
135
+ if (isRelationChoice) {
136
+ onChange(id, content, {
137
+ image_field: 'image',
138
+ image_scales: { image: [image] },
139
+ });
140
+ } else {
141
+ onChange(id, imageId, {
142
+ image_field: 'image',
143
+ image_scales: { image: [image] },
144
+ });
145
+ }
120
146
  }
121
- }, [loading, loaded, uploading, imageId, image, id, onChange]); // Explicitly list all dependencies
147
+ }, [
148
+ loading,
149
+ loaded,
150
+ uploading,
151
+ imageId,
152
+ image,
153
+ id,
154
+ content,
155
+ isRelationChoice,
156
+ onChange,
157
+ ]);
122
158
 
123
159
  loading = usePrevious(props.request?.loading);
124
160
 
125
161
  const handleUpload = React.useCallback(
126
162
  (eventOrFile) => {
163
+ let uploadUrl = getBaseUrl(contextUrl);
164
+ if (!isFolderish) uploadUrl = getParentUrl(uploadUrl);
127
165
  if (restrictFileUpload === true) return;
128
166
  eventOrFile.target && eventOrFile.stopPropagation();
129
167
 
@@ -131,12 +169,15 @@ const UnconnectedImageInput = (props) => {
131
169
  const file = eventOrFile.target
132
170
  ? eventOrFile.target.files[0]
133
171
  : eventOrFile[0];
134
- if (!validateFileUploadSize(file, intl.formatMessage)) return;
172
+ if (!validateFileUploadSize(file, intl.formatMessage)) {
173
+ setUploading(false);
174
+ return;
175
+ }
135
176
  readAsDataURL(file).then((fileData) => {
136
177
  const fields = fileData.match(/^data:(.*);(.*),(.*)$/);
137
178
  dispatch(
138
179
  createContent(
139
- getBaseUrl(contextUrl),
180
+ uploadUrl,
140
181
  {
141
182
  '@type': 'Image',
142
183
  title: file.name,
@@ -153,11 +194,12 @@ const UnconnectedImageInput = (props) => {
153
194
  });
154
195
  },
155
196
  [
197
+ contextUrl,
198
+ isFolderish,
156
199
  restrictFileUpload,
157
200
  intl.formatMessage,
158
201
  dispatch,
159
- props,
160
- contextUrl,
202
+ props.block,
161
203
  requestId,
162
204
  ],
163
205
  );
@@ -167,6 +209,83 @@ const UnconnectedImageInput = (props) => {
167
209
  }, [restrictFileUpload]);
168
210
  const onDragLeave = React.useCallback(() => setDragging(false), []);
169
211
 
212
+ const validateManualLink = React.useCallback(
213
+ (url) => {
214
+ if (!url.startsWith('/')) {
215
+ const error = urlValidator({
216
+ value: url,
217
+ formatMessage: intl.formatMessage,
218
+ });
219
+ // if (error && url !== '') {
220
+ // this.setState({ errors: [error] });
221
+ // } else {
222
+ // this.setState({ errors: [] });
223
+ // }
224
+ return !Boolean(error);
225
+ } else {
226
+ return isInternalURL(url);
227
+ }
228
+ },
229
+ [intl.formatMessage],
230
+ );
231
+
232
+ const onSubmitURL = React.useCallback(
233
+ (url) => {
234
+ if (validateManualLink(url)) {
235
+ if (isInternalURL(url)) {
236
+ // convert it into an internal on if possible
237
+ props
238
+ .searchContent(
239
+ '/',
240
+ {
241
+ portal_type: config.settings.imageObjects,
242
+ 'path.query': flattenToAppURL(url),
243
+ 'path.depth': '0',
244
+ sort_on: 'getObjPositionInParent',
245
+ metadata_fields: '_all',
246
+ b_size: 1000,
247
+ },
248
+ `${props.block}-${props.mode}`,
249
+ )
250
+ .then((resp) => {
251
+ if (resp.items?.length > 0) {
252
+ onChange(props.id, resp.items[0], {});
253
+ } else {
254
+ toast.error(
255
+ <Toast
256
+ error
257
+ title={intl.formatMessage(messages.Error)}
258
+ content={intl.formatMessage(
259
+ messages.internalImageNotFoundErrorMessage,
260
+ )}
261
+ />,
262
+ );
263
+ }
264
+ });
265
+ } else {
266
+ if (isRelationChoice) {
267
+ toast.error(
268
+ <Toast
269
+ error
270
+ title={intl.formatMessage(messages.Error)}
271
+ content={intl.formatMessage(messages.imageUploadErrorMessage)}
272
+ />,
273
+ );
274
+ } else {
275
+ // if it's an external link, we save it as is
276
+ onChange(props.id, [
277
+ {
278
+ '@id': normalizeUrl(url),
279
+ title: removeProtocol(url),
280
+ },
281
+ ]);
282
+ }
283
+ }
284
+ }
285
+ },
286
+ [validateManualLink, props, intl, isRelationChoice, onChange],
287
+ );
288
+
170
289
  return imageValue ? (
171
290
  <div
172
291
  className="image-upload-widget-image"
@@ -175,15 +294,20 @@ const UnconnectedImageInput = (props) => {
175
294
  role="toolbar"
176
295
  >
177
296
  {selected && <ImageToolbar {...props} />}
178
- <img
179
- className={props.className}
180
- src={
181
- isInternalURL(imageValue)
182
- ? `${flattenToAppURL(imageValue)}/@@images/image/${imageSize}`
183
- : imageValue
184
- }
185
- alt=""
186
- />
297
+ {/* If it's relation choice (preview_image_link) */}
298
+ {isRelationChoice ? (
299
+ <Image item={value} width="fit-content" height="auto" loading="lazy" />
300
+ ) : (
301
+ <Image
302
+ className={props.className}
303
+ src={
304
+ isInternalURL(imageValue)
305
+ ? `${flattenToAppURL(imageValue)}/@@images/image/${imageSize}`
306
+ : imageValue
307
+ }
308
+ alt=""
309
+ />
310
+ )}
187
311
  </div>
188
312
  ) : (
189
313
  <div
@@ -196,10 +320,10 @@ const UnconnectedImageInput = (props) => {
196
320
  noClick
197
321
  accept="image/*"
198
322
  onDrop={(acceptedFiles) => {
323
+ setDragging(false);
199
324
  if (acceptedFiles.length > 0) {
200
325
  handleUpload(acceptedFiles);
201
326
  } else {
202
- setDragging(false);
203
327
  toast.error(
204
328
  <Toast
205
329
  error
@@ -224,7 +348,7 @@ const UnconnectedImageInput = (props) => {
224
348
  </Loader>
225
349
  </Dimmer>
226
350
  )}
227
- <img src={imageBlockSVG} alt="" className="placeholder" />
351
+ <Image src={imageBlockSVG} alt="" className="placeholder" />
228
352
  <p>{description || intl.formatMessage(messages.addImage)}</p>
229
353
  <div className="toolbar-wrapper">
230
354
  <div className="toolbar-inner" ref={linkEditor.anchorNode}>
@@ -239,15 +363,24 @@ const UnconnectedImageInput = (props) => {
239
363
  e.preventDefault();
240
364
  openObjectBrowser({
241
365
  mode: objectBrowserPickerType,
242
- onSelectItem: onSelectItem
243
- ? onSelectItem
244
- : (url, { title, image_field, image_scales }) => {
245
- onChange(props.id, flattenToAppURL(url), {
246
- title,
247
- image_field,
248
- image_scales,
249
- });
250
- },
366
+ onSelectItem: isRelationChoice
367
+ ? (url, item) => {
368
+ // we save the whole item if it's a relation choice
369
+ onChange(props.id, item);
370
+ }
371
+ : onSelectItem
372
+ ? onSelectItem
373
+ : // else we save the url along with the image field and scales
374
+ (
375
+ url,
376
+ { title, image_field, image_scales },
377
+ ) => {
378
+ onChange(props.id, flattenToAppURL(url), {
379
+ title,
380
+ image_field,
381
+ image_scales,
382
+ });
383
+ },
251
384
  currentPath: contextUrl,
252
385
  });
253
386
  }}
@@ -308,13 +441,14 @@ const UnconnectedImageInput = (props) => {
308
441
  intl.formatMessage(messages.linkAnImage)
309
442
  }
310
443
  objectBrowserPickerType={objectBrowserPickerType}
311
- onChange={(_, e) =>
312
- onChange(
313
- props.id,
314
- isInternalURL(e) ? flattenToAppURL(e) : e,
315
- {},
316
- )
317
- }
444
+ onChange={(_, e) => {
445
+ onSubmitURL(e);
446
+ // onChange(
447
+ // props.id,
448
+ // isInternalURL(e) ? flattenToAppURL(e) : e,
449
+ // {},
450
+ // );
451
+ }}
318
452
  id={id}
319
453
  />
320
454
  )}
@@ -328,6 +462,8 @@ const UnconnectedImageInput = (props) => {
328
462
  };
329
463
 
330
464
  export const ImageInput = compose(
465
+ // This HOC goes first because it injects block in case that it's not present (not a block, but a DX field)
466
+ withObjectBrowser,
331
467
  connect(
332
468
  (state, ownProps) => {
333
469
  const requestId = `image-upload-${ownProps.id}`;
@@ -336,9 +472,9 @@ export const ImageInput = compose(
336
472
  content: state.content.subrequests[ownProps.block || requestId]?.data,
337
473
  };
338
474
  },
339
- { createContent },
475
+ { createContent, searchContent },
340
476
  ),
341
- )(withObjectBrowser(UnconnectedImageInput));
477
+ )(UnconnectedImageInput);
342
478
 
343
479
  const ImageUploadWidget = (props) => {
344
480
  const { fieldSet, id, title } = props;
@@ -100,6 +100,7 @@ export const InternalUrlWidget = (props) => {
100
100
  {value?.length > 0 ? (
101
101
  <Button.Group>
102
102
  <Button
103
+ type="button"
103
104
  basic
104
105
  className="cancel"
105
106
  aria-label="clearUrlBrowser"
@@ -115,6 +116,7 @@ export const InternalUrlWidget = (props) => {
115
116
  ) : (
116
117
  <Button.Group>
117
118
  <Button
119
+ type="button"
118
120
  basic
119
121
  icon
120
122
  aria-label="openUrlBrowser"
@@ -16,13 +16,14 @@ test('renders a number widget component', () => {
16
16
  });
17
17
  const component = renderer.create(
18
18
  <Provider store={store}>
19
- <NumberWidget
20
- id="my-field"
21
- title="My field"
22
- fieldSet="default"
23
- onChange={() => {}}
24
- />
25
- ,
19
+ <>
20
+ <NumberWidget
21
+ id="my-field"
22
+ title="My field"
23
+ fieldSet="default"
24
+ onChange={() => {}}
25
+ />
26
+ </>
26
27
  </Provider>,
27
28
  );
28
29
  const json = component.toJSON();
@@ -399,6 +399,7 @@ export class ObjectBrowserWidgetComponent extends Component {
399
399
  {this.state.manualLinkInput && isEmpty(items) && (
400
400
  <Button.Group>
401
401
  <Button
402
+ type="button"
402
403
  basic
403
404
  className="cancel"
404
405
  onClick={(e) => {
@@ -409,6 +410,7 @@ export class ObjectBrowserWidgetComponent extends Component {
409
410
  <Icon name={clearSVG} size="18px" color="#e40166" />
410
411
  </Button>
411
412
  <Button
413
+ type="button"
412
414
  basic
413
415
  primary
414
416
  disabled={!this.state.validURL}
@@ -423,6 +425,7 @@ export class ObjectBrowserWidgetComponent extends Component {
423
425
  )}
424
426
  {!this.state.manualLinkInput && (
425
427
  <Button
428
+ type="button"
426
429
  aria-label={this.props.intl.formatMessage(
427
430
  messages.openObjectBrowser,
428
431
  )}
@@ -14,6 +14,7 @@ import deleteSVG from '@plone/volto/icons/delete.svg';
14
14
  import addSVG from '@plone/volto/icons/add.svg';
15
15
  import dragSVG from '@plone/volto/icons/drag.svg';
16
16
  import { v4 as uuid } from 'uuid';
17
+ import config from '@plone/volto/registry';
17
18
 
18
19
  const messages = defineMessages({
19
20
  labelRemoveItem: {
@@ -71,11 +72,20 @@ const ObjectListWidget = (props) => {
71
72
  block,
72
73
  fieldSet,
73
74
  id,
74
- schema,
75
75
  value = [],
76
76
  onChange,
77
77
  schemaExtender,
78
+ schemaName,
78
79
  } = props;
80
+
81
+ // This allows to use a `schemaName` prop defined as source of the schema
82
+ // if not present, it will use the schema defined in the schema prop
83
+ const schema =
84
+ config.getUtility({
85
+ type: 'schema',
86
+ name: schemaName,
87
+ }).method || props.schema;
88
+
79
89
  const [localActiveObject, setLocalActiveObject] = React.useState(
80
90
  props.activeObject ?? value.length - 1,
81
91
  );
@@ -4,20 +4,30 @@ import { render } from '@testing-library/react';
4
4
  import configureStore from 'redux-mock-store';
5
5
  import ObjectListWidget from './ObjectListWidget';
6
6
 
7
- jest.mock('@plone/volto/helpers/Loadable/Loadable');
8
- jest.mock('@plone/volto/components/manage/Form');
7
+ vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
8
+ return await import(
9
+ '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
10
+ );
11
+ });
12
+ vi.mock('@plone/volto/components/manage/Form', async () => {
13
+ return await import(
14
+ '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
15
+ );
16
+ });
9
17
 
10
- beforeAll(
11
- async () =>
12
- await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
13
- );
18
+ beforeAll(async () => {
19
+ const { __setLoadables } = await import(
20
+ '@plone/volto/helpers/Loadable/Loadable'
21
+ );
22
+ await __setLoadables();
23
+ });
14
24
 
15
25
  let mockSerial = 0;
16
26
  const mockStore = configureStore();
17
27
 
18
- jest.mock('uuid', () => {
28
+ vi.mock('uuid', () => {
19
29
  return {
20
- v4: jest.fn().mockImplementation(() => `id-${mockSerial++}`),
30
+ v4: vi.fn().mockImplementation(() => `id-${mockSerial++}`),
21
31
  };
22
32
  });
23
33
 
@@ -5,7 +5,11 @@ import { Provider } from 'react-intl-redux';
5
5
  import { render, fireEvent } from '@testing-library/react';
6
6
  import ObjectWidget from './ObjectWidget';
7
7
 
8
- jest.mock('@plone/volto/components/manage/Form');
8
+ vi.mock('@plone/volto/components/manage/Form', async () => {
9
+ return await import(
10
+ '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
11
+ );
12
+ });
9
13
 
10
14
  const mockStore = configureStore();
11
15
 
@@ -7,11 +7,18 @@ import RadioGroupWidget from './RadioGroupWidget';
7
7
 
8
8
  const mockStore = configureStore();
9
9
 
10
- jest.mock('@plone/volto/helpers/Loadable/Loadable');
11
- beforeAll(
12
- async () =>
13
- await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
14
- );
10
+ vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
11
+ return await import(
12
+ '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
13
+ );
14
+ });
15
+
16
+ beforeAll(async () => {
17
+ const { __setLoadables } = await import(
18
+ '@plone/volto/helpers/Loadable/Loadable'
19
+ );
20
+ await __setLoadables();
21
+ });
15
22
 
16
23
  test('renders a radio group widget component', async () => {
17
24
  const store = mockStore({
@@ -3,14 +3,20 @@ import renderer from 'react-test-renderer';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import { waitFor } from '@testing-library/react';
6
-
7
6
  import RecurrenceWidget from './RecurrenceWidget';
8
7
 
9
- jest.mock('@plone/volto/helpers/Loadable/Loadable');
10
- beforeAll(
11
- async () =>
12
- await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
13
- );
8
+ vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
9
+ return await import(
10
+ '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
11
+ );
12
+ });
13
+
14
+ beforeAll(async () => {
15
+ const { __setLoadables } = await import(
16
+ '@plone/volto/helpers/Loadable/Loadable'
17
+ );
18
+ await __setLoadables();
19
+ });
14
20
 
15
21
  const mockStore = configureStore();
16
22