@plone/volto 19.0.0-alpha.2 → 19.0.0-alpha.20

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 (366) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc +37 -3
  3. package/CHANGELOG.md +338 -1
  4. package/README.md +20 -16
  5. package/babel.js +1 -3
  6. package/cypress/docker/prefixed-rules.yml +26 -0
  7. package/cypress/docker/prefixed.yml +24 -0
  8. package/cypress/support/commands.js +12 -6
  9. package/cypress/support/guillotina.js +1 -0
  10. package/cypress.config.js +1 -0
  11. package/global-test-setup.js +1 -2
  12. package/locales/af.json +1 -0
  13. package/locales/ar.json +1 -0
  14. package/locales/bg.json +1 -0
  15. package/locales/bn.json +1 -0
  16. package/locales/ca/LC_MESSAGES/volto.po +124 -17
  17. package/locales/ca.json +1 -1
  18. package/locales/cs.json +1 -0
  19. package/locales/cy.json +1 -0
  20. package/locales/da.json +1 -0
  21. package/locales/de/LC_MESSAGES/volto.po +135 -28
  22. package/locales/de.json +1 -1
  23. package/locales/el.json +1 -0
  24. package/locales/en/LC_MESSAGES/volto.po +125 -18
  25. package/locales/en.json +1 -1
  26. package/locales/en_AU.json +1 -0
  27. package/locales/en_GB.json +1 -0
  28. package/locales/eo.json +1 -0
  29. package/locales/es/LC_MESSAGES/volto.po +125 -18
  30. package/locales/es.json +1 -1
  31. package/locales/et.json +1 -0
  32. package/locales/eu/LC_MESSAGES/volto.po +124 -17
  33. package/locales/eu.json +1 -1
  34. package/locales/fa.json +1 -0
  35. package/locales/fi/LC_MESSAGES/volto.po +124 -17
  36. package/locales/fi.json +1 -1
  37. package/locales/fr/LC_MESSAGES/volto.po +125 -18
  38. package/locales/fr.json +1 -1
  39. package/locales/fu.json +1 -0
  40. package/locales/gl.json +1 -0
  41. package/locales/he.json +1 -0
  42. package/locales/hi/LC_MESSAGES/volto.po +128 -21
  43. package/locales/hi.json +1 -1
  44. package/locales/hr.json +1 -0
  45. package/locales/hu.json +1 -0
  46. package/locales/hy.json +1 -0
  47. package/locales/id.json +1 -0
  48. package/locales/it/LC_MESSAGES/volto.po +129 -22
  49. package/locales/it.json +1 -1
  50. package/locales/ja/LC_MESSAGES/volto.po +124 -17
  51. package/locales/ja.json +1 -1
  52. package/locales/ka.json +1 -0
  53. package/locales/kn.json +1 -0
  54. package/locales/ko.json +1 -0
  55. package/locales/lt.json +1 -0
  56. package/locales/lv.json +1 -0
  57. package/locales/mi.json +1 -0
  58. package/locales/mk.json +1 -0
  59. package/locales/my.json +1 -0
  60. package/locales/nb_NO.json +1 -0
  61. package/locales/nl/LC_MESSAGES/volto.po +128 -21
  62. package/locales/nl.json +1 -1
  63. package/locales/nn.json +1 -0
  64. package/locales/pl.json +1 -0
  65. package/locales/pt/LC_MESSAGES/volto.po +124 -17
  66. package/locales/pt.json +1 -1
  67. package/locales/pt_BR/LC_MESSAGES/volto.po +147 -40
  68. package/locales/pt_BR.json +1 -1
  69. package/locales/rm.json +1 -0
  70. package/locales/ro/LC_MESSAGES/volto.po +128 -21
  71. package/locales/ro.json +1 -1
  72. package/locales/ru/LC_MESSAGES/volto.po +128 -21
  73. package/locales/ru.json +1 -1
  74. package/locales/sk.json +1 -0
  75. package/locales/sl.json +1 -0
  76. package/locales/sm.json +1 -0
  77. package/locales/sq.json +1 -0
  78. package/locales/sr.json +1 -0
  79. package/locales/sr@cyrl.json +1 -0
  80. package/locales/sr@latn.json +1 -0
  81. package/locales/sv.json +1 -1
  82. package/locales/ta.json +1 -0
  83. package/locales/te.json +1 -0
  84. package/locales/th.json +1 -0
  85. package/locales/to.json +1 -0
  86. package/locales/tr.json +1 -0
  87. package/locales/uk.json +1 -0
  88. package/locales/vi.json +1 -0
  89. package/locales/volto.pot +125 -18
  90. package/locales/zh_CN/LC_MESSAGES/volto.po +124 -17
  91. package/locales/zh_CN.json +1 -1
  92. package/locales/zh_Hant.json +1 -0
  93. package/locales/zh_Hant_HK.json +1 -0
  94. package/package.json +43 -100
  95. package/razzle.config.js +21 -21
  96. package/src/actions/content/content.js +0 -1
  97. package/src/actions/controlpanels/controlpanels.js +13 -7
  98. package/src/actions/controlpanels/controlpanels.test.js +11 -5
  99. package/src/actions/users/users.js +2 -2
  100. package/src/components/manage/Actions/Actions.test.jsx +1 -5
  101. package/src/components/manage/Add/Add.jsx +5 -6
  102. package/src/components/manage/BlockChooser/BlockChooser.jsx +1 -0
  103. package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +1 -5
  104. package/src/components/manage/Blocks/Block/Edit.jsx +1 -0
  105. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +9 -4
  106. package/src/components/manage/Blocks/Block/Settings.test.jsx +1 -5
  107. package/src/components/manage/Blocks/HTML/Edit.test.jsx +1 -5
  108. package/src/components/manage/Blocks/Image/Edit.jsx +5 -1
  109. package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +1 -5
  110. package/src/components/manage/Blocks/LeadImage/Edit.jsx +2 -2
  111. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +1 -1
  112. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +1 -5
  113. package/src/components/manage/Blocks/Listing/ImageGallery.jsx +6 -4
  114. package/src/components/manage/Blocks/Maps/Edit.jsx +2 -1
  115. package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +1 -5
  116. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +21 -4
  117. package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +1 -6
  118. package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +1 -6
  119. package/src/components/manage/Blocks/Teaser/Data.jsx +21 -7
  120. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +1 -1
  121. package/src/components/manage/Blocks/Teaser/schema.js +8 -3
  122. package/src/components/manage/Blocks/Video/Edit.jsx +2 -1
  123. package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +1 -5
  124. package/src/components/manage/Contents/Contents.jsx +689 -654
  125. package/src/components/manage/Contents/Contents.test.jsx +8 -5
  126. package/src/components/manage/Contents/ContentsBreadcrumbs.Multilingual.test.jsx +18 -5
  127. package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +20 -26
  128. package/src/components/manage/Contents/ContentsBreadcrumbs.test.jsx +14 -0
  129. package/src/components/manage/Contents/ContentsDeleteModal.jsx +258 -206
  130. package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +26 -8
  131. package/src/components/manage/Contents/ContentsItem.jsx +10 -2
  132. package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +1 -5
  133. package/src/components/manage/Contents/ContentsRenameModal.test.jsx +1 -5
  134. package/src/components/manage/Contents/ContentsTagsModal.test.jsx +1 -5
  135. package/src/components/manage/Contents/ContentsUploadModal.test.jsx +13 -22
  136. package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +1 -5
  137. package/src/components/manage/Contents/DropZoneContent.jsx +323 -0
  138. package/src/components/manage/Contents/__mocks__/index.tsx +2 -18
  139. package/src/components/manage/Controlpanels/Aliases.test.jsx +1 -5
  140. package/src/components/manage/Controlpanels/ContentType.jsx +1 -1
  141. package/src/components/manage/Controlpanels/ContentType.test.jsx +1 -5
  142. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +3 -2
  143. package/src/components/manage/Controlpanels/Relations/Relations.jsx +1 -1
  144. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +1 -5
  145. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +1 -5
  146. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +1 -5
  147. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +156 -175
  148. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +575 -630
  149. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +4 -3
  150. package/src/components/manage/Diff/Diff.test.jsx +1 -6
  151. package/src/components/manage/Diff/DiffField.test.jsx +1 -6
  152. package/src/components/manage/Display/Display.test.jsx +2 -11
  153. package/src/components/manage/Edit/Edit.jsx +2 -3
  154. package/src/components/manage/Edit/Edit.test.jsx +1 -5
  155. package/src/components/manage/Form/BlockDataForm.test.jsx +1 -5
  156. package/src/components/manage/Form/Form.test.jsx +1 -5
  157. package/src/components/manage/Form/InlineForm.jsx +2 -2
  158. package/src/components/manage/Form/InlineForm.test.jsx +1 -5
  159. package/src/components/manage/Form/ModalForm.jsx +12 -10
  160. package/src/components/manage/Form/ModalForm.test.jsx +27 -5
  161. package/src/components/manage/Form/__mocks__/index.tsx +9 -27
  162. package/src/components/manage/Multilingual/CompareLanguages.jsx +2 -5
  163. package/src/components/manage/Multilingual/CreateTranslation.jsx +8 -8
  164. package/src/components/manage/Multilingual/ManageTranslations.jsx +4 -2
  165. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +5 -1
  166. package/src/components/manage/Multilingual/TranslationObject.jsx +1 -1
  167. package/src/components/manage/Preferences/ChangePassword.test.jsx +1 -5
  168. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +1 -17
  169. package/src/components/manage/Sidebar/ObjectBrowser.jsx +3 -0
  170. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +13 -1
  171. package/src/components/manage/Sidebar/ObjectBrowserNav.jsx +2 -1
  172. package/src/components/manage/Sidebar/SidebarPortal.test.tsx +42 -0
  173. package/src/components/manage/Sidebar/SidebarPortal.tsx +48 -0
  174. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +2 -1
  175. package/src/components/manage/Toolbar/More.jsx +4 -1
  176. package/src/components/manage/Toolbar/More.test.jsx +3 -0
  177. package/src/components/manage/Toolbar/PersonalTools.jsx +2 -1
  178. package/src/components/manage/Toolbar/Toolbar.jsx +3 -4
  179. package/src/components/manage/Toolbar/Types.jsx +7 -7
  180. package/src/components/manage/UniversalLink/UniversalLink.tsx +1 -0
  181. package/src/components/manage/Widgets/AlignWidget.stories.jsx +9 -0
  182. package/src/components/manage/Widgets/AlignWidget.test.tsx +95 -0
  183. package/src/components/manage/Widgets/{AlignWidget.jsx → AlignWidget.tsx} +23 -7
  184. package/src/components/manage/Widgets/ArrayWidget.test.jsx +1 -6
  185. package/src/components/manage/Widgets/BlockAlignment.stories.tsx +104 -0
  186. package/src/components/manage/Widgets/BlockAlignment.test.tsx +104 -0
  187. package/src/components/manage/Widgets/BlockAlignment.tsx +88 -0
  188. package/src/components/manage/Widgets/BlockWidth.stories.tsx +69 -0
  189. package/src/components/manage/Widgets/BlockWidth.test.tsx +62 -0
  190. package/src/components/manage/Widgets/BlockWidth.tsx +101 -0
  191. package/src/components/manage/Widgets/ButtonsWidget.stories.jsx +61 -0
  192. package/src/components/manage/Widgets/ButtonsWidget.test.tsx +138 -0
  193. package/src/components/manage/Widgets/ButtonsWidget.tsx +176 -0
  194. package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +1 -6
  195. package/src/components/manage/Widgets/DatetimeWidget.jsx +16 -1
  196. package/src/components/manage/Widgets/DatetimeWidget.test.jsx +1 -6
  197. package/src/components/manage/Widgets/FileWidget.jsx +14 -8
  198. package/src/components/manage/Widgets/FormFieldWrapper.jsx +146 -168
  199. package/src/components/manage/Widgets/ImageWidget.jsx +171 -38
  200. package/src/components/manage/Widgets/InternalUrlWidget.jsx +2 -0
  201. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +8 -0
  202. package/src/components/manage/Widgets/ObjectListWidget.test.jsx +2 -11
  203. package/src/components/manage/Widgets/ObjectWidget.test.jsx +1 -5
  204. package/src/components/manage/Widgets/QueryWidget.jsx +137 -9
  205. package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +1 -6
  206. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +1 -6
  207. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +3 -2
  208. package/src/components/manage/Widgets/SchemaWidget.test.jsx +1 -6
  209. package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +1 -6
  210. package/src/components/manage/Widgets/SelectAutoComplete.jsx +29 -12
  211. package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +1 -6
  212. package/src/components/manage/Widgets/SelectWidget.test.jsx +1 -6
  213. package/src/components/manage/Widgets/Size.stories.tsx +69 -0
  214. package/src/components/manage/Widgets/Size.test.tsx +59 -0
  215. package/src/components/manage/Widgets/Size.tsx +78 -0
  216. package/src/components/manage/Widgets/TimeWidget.test.jsx +1 -6
  217. package/src/components/manage/Widgets/TokenWidget.test.jsx +1 -6
  218. package/src/components/manage/Widgets/UrlWidget.jsx +2 -0
  219. package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +2 -11
  220. package/src/components/manage/Widgets/__mocks__/index.tsx +33 -51
  221. package/src/components/manage/Widgets/index.tsx +21 -0
  222. package/src/components/manage/Workflow/Workflow.test.jsx +2 -11
  223. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -3
  224. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +0 -4
  225. package/src/components/theme/App/App.jsx +5 -1
  226. package/src/components/theme/App/App.test.jsx +1 -0
  227. package/src/components/theme/Avatar/Avatar.jsx +2 -1
  228. package/src/components/theme/Comments/CommentEditModal.test.jsx +1 -5
  229. package/src/components/theme/Comments/Comments.test.jsx +2 -11
  230. package/src/components/theme/ContactForm/ContactForm.test.jsx +1 -5
  231. package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +20 -2
  232. package/src/components/theme/Image/Image.jsx +11 -8
  233. package/src/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.tsx +7 -0
  234. package/src/components/theme/LanguageSelector/{LanguageSelector.test.jsx → LanguageSelector.test.tsx} +6 -6
  235. package/src/components/theme/LanguageSelector/LanguageSelector.tsx +89 -0
  236. package/src/components/theme/Logo/Logo.Multilingual.test.jsx +0 -5
  237. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +10 -14
  238. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +3 -5
  239. package/src/components/theme/Navigation/NavItem.jsx +1 -5
  240. package/src/components/theme/Navigation/Navigation.Multilingual.test.jsx +0 -5
  241. package/src/components/theme/NotFound/NotFound.jsx +5 -2
  242. package/src/components/theme/NotFound/NotFound.test.jsx +3 -0
  243. package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +1 -5
  244. package/src/components/theme/PreviewImage/PreviewImage.jsx +1 -1
  245. package/src/components/theme/Register/Register.test.jsx +1 -5
  246. package/src/components/theme/RequestTimeout/RequestTimeout.jsx +1 -1
  247. package/src/components/theme/Sitemap/Sitemap.jsx +6 -5
  248. package/src/components/theme/Sitemap/Sitemap.test.jsx +0 -1
  249. package/src/components/theme/Unauthorized/Unauthorized.jsx +5 -2
  250. package/src/components/theme/View/EventDatesInfo.test.jsx +1 -6
  251. package/src/components/theme/View/EventView.test.jsx +1 -6
  252. package/src/components/theme/View/FileView.jsx +9 -1
  253. package/src/components/theme/View/View.jsx +8 -1
  254. package/src/components/theme/Widgets/ImageWidget.jsx +2 -1
  255. package/src/config/ControlPanels.js +1 -0
  256. package/src/config/Widgets.jsx +7 -0
  257. package/src/config/index.js +18 -25
  258. package/src/config/server.js +0 -2
  259. package/src/config/slots.js +19 -0
  260. package/src/express-middleware/devproxy.js +20 -5
  261. package/src/helpers/Api/APIResourceWithAuth.js +8 -3
  262. package/src/helpers/Api/Api.js +7 -4
  263. package/src/helpers/AsyncConnect/ssr.js +4 -1
  264. package/src/helpers/Content/Content.js +23 -0
  265. package/src/helpers/Content/Content.test.js +39 -0
  266. package/src/helpers/Content/withClientSideContent.jsx +35 -0
  267. package/src/helpers/Extensions/withBlockSchemaEnhancer.jsx +4 -1
  268. package/src/helpers/Html/Html.jsx +13 -7
  269. package/src/helpers/LanguageMap/LanguageMap.js +115 -8
  270. package/src/helpers/Loadable/__mocks__/Loadable.jsx +7 -22
  271. package/src/helpers/MessageLabels/MessageLabels.js +5 -0
  272. package/src/helpers/Sitemap/Sitemap.js +4 -4
  273. package/src/helpers/Url/Url.js +33 -2
  274. package/src/helpers/Url/Url.test.js +62 -0
  275. package/src/hooks/user/useUser.js +1 -1
  276. package/src/internalChecks.test.ts +11 -0
  277. package/src/middleware/Api.test.js +4 -0
  278. package/src/middleware/api.js +82 -28
  279. package/src/middleware/storeProtectLoadUtils.test.js +3 -3
  280. package/src/reducers/content/content.js +3 -18
  281. package/src/reducers/diff/diff.js +5 -1
  282. package/src/reducers/diff/diff.test.js +60 -4
  283. package/src/reducers/querystring/querystring.js +8 -1
  284. package/src/routes.js +4 -2
  285. package/src/server.jsx +45 -14
  286. package/src/start-client.jsx +9 -6
  287. package/src/start-server.js +9 -3
  288. package/test-addons-loader.js +3 -0
  289. package/test-setup-config.jsx +0 -2
  290. package/test-setup-globals.js +30 -2
  291. package/theme/themes/pastanaga/extras/blocks.less +26 -0
  292. package/theme/themes/pastanaga/extras/contents.less +80 -5
  293. package/theme/themes/pastanaga/extras/main.less +17 -2
  294. package/theme/themes/pastanaga/extras/widgets.less +79 -0
  295. package/tsconfig.declarations.json +1 -1
  296. package/tsconfig.json +4 -5
  297. package/types/components/manage/Blocks/Teaser/schema.d.ts +1 -0
  298. package/types/components/manage/Contents/DropZoneContent.d.ts +2 -0
  299. package/types/components/manage/Contents/__mocks__/index.d.ts +2 -2
  300. package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
  301. package/types/components/manage/Controlpanels/Users/RenderUsers.d.ts +18 -2
  302. package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +6 -2
  303. package/types/components/manage/Controlpanels/index.d.ts +2 -2
  304. package/types/components/manage/Form/__mocks__/index.d.ts +8 -8
  305. package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
  306. package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
  307. package/types/components/manage/Sidebar/SidebarPortal.d.ts +7 -15
  308. package/types/components/manage/Widgets/AlignWidget.d.ts +8 -10
  309. package/types/components/manage/Widgets/AlignWidget.stories.d.ts +1 -0
  310. package/types/components/manage/Widgets/BlockAlignment.d.ts +7 -0
  311. package/types/components/manage/Widgets/BlockAlignment.stories.d.ts +8 -0
  312. package/types/components/manage/Widgets/BlockWidth.d.ts +7 -0
  313. package/types/components/manage/Widgets/BlockWidth.stories.d.ts +6 -0
  314. package/types/components/manage/Widgets/ButtonsWidget.d.ts +48 -1
  315. package/types/components/manage/Widgets/ButtonsWidget.stories.d.ts +3 -0
  316. package/types/components/manage/Widgets/FormFieldWrapper.d.ts +28 -5
  317. package/types/components/manage/Widgets/ImageWidget.d.ts +41 -1
  318. package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
  319. package/types/components/manage/Widgets/ObjectBrowserWidget.d.ts +2 -0
  320. package/types/components/manage/Widgets/QueryWidget.d.ts +5 -2
  321. package/types/components/manage/Widgets/RecurrenceWidget/Utils.d.ts +12 -18
  322. package/types/components/manage/Widgets/Size.d.ts +7 -0
  323. package/types/components/manage/Widgets/Size.stories.d.ts +6 -0
  324. package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
  325. package/types/components/manage/Widgets/__mocks__/index.d.ts +33 -33
  326. package/types/components/manage/Widgets/index.d.ts +11 -6
  327. package/types/components/theme/FormattedDate/FormattedDate.stories.d.ts +1 -1
  328. package/types/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.d.ts +3 -0
  329. package/types/components/theme/LanguageSelector/LanguageSelector.d.ts +3 -10
  330. package/types/components/theme/Unauthorized/Unauthorized.d.ts +2 -2
  331. package/types/config/Widgets.d.ts +6 -0
  332. package/types/config/slots.d.ts +7 -0
  333. package/types/helpers/Content/Content.d.ts +7 -0
  334. package/types/helpers/Content/withClientSideContent.d.ts +1 -0
  335. package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +4 -5
  336. package/types/helpers/Helmet/Helmet.d.ts +1 -1
  337. package/types/helpers/LanguageMap/LanguageMap.d.ts +428 -4
  338. package/types/helpers/Loadable/__mocks__/Loadable.d.ts +2 -2
  339. package/types/helpers/MessageLabels/MessageLabels.d.ts +68 -62
  340. package/types/helpers/Url/Url.d.ts +14 -0
  341. package/types/helpers/Url/bulkFlattenToAppURL.d.ts +5 -0
  342. package/types/middleware/api.d.ts +6 -9
  343. package/types/reducers/index.d.ts +1 -0
  344. package/types/start-client.d.ts +0 -1
  345. package/vitest.config.mjs +4 -4
  346. package/webpack-plugins/webpack-scss-plugin.js +172 -0
  347. package/jest-addons-loader.js +0 -3
  348. package/jest-extender-plugin.js +0 -39
  349. package/jest-setup-afterenv.js +0 -2
  350. package/jest-svgsystem-transform.js +0 -10
  351. package/package-why.json +0 -34
  352. package/patches/patchit.sh +0 -2
  353. package/patches/razzle-jest.patch +0 -10
  354. package/src/actions/content/content.multilingual.test.js +0 -17
  355. package/src/components/manage/Contents/__mocks__/index.vitest.tsx +0 -5
  356. package/src/components/manage/Form/__mocks__/index.vitest.tsx +0 -73
  357. package/src/components/manage/Sidebar/SidebarPortal.jsx +0 -47
  358. package/src/components/manage/Sidebar/SidebarPortal.test.jsx +0 -26
  359. package/src/components/manage/Widgets/AlignWidget.test.jsx +0 -59
  360. package/src/components/manage/Widgets/ButtonsWidget.jsx +0 -41
  361. package/src/components/manage/Widgets/ButtonsWidget.test.jsx +0 -70
  362. package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +0 -41
  363. package/src/components/theme/LanguageSelector/LanguageSelector.jsx +0 -77
  364. package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +0 -39
  365. package/test-setup-globals-vitest.js +0 -46
  366. 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
 
@@ -139,7 +177,7 @@ const UnconnectedImageInput = (props) => {
139
177
  const fields = fileData.match(/^data:(.*);(.*),(.*)$/);
140
178
  dispatch(
141
179
  createContent(
142
- getBaseUrl(contextUrl),
180
+ uploadUrl,
143
181
  {
144
182
  '@type': 'Image',
145
183
  title: file.name,
@@ -156,11 +194,12 @@ const UnconnectedImageInput = (props) => {
156
194
  });
157
195
  },
158
196
  [
197
+ contextUrl,
198
+ isFolderish,
159
199
  restrictFileUpload,
160
200
  intl.formatMessage,
161
201
  dispatch,
162
- props,
163
- contextUrl,
202
+ props.block,
164
203
  requestId,
165
204
  ],
166
205
  );
@@ -170,6 +209,83 @@ const UnconnectedImageInput = (props) => {
170
209
  }, [restrictFileUpload]);
171
210
  const onDragLeave = React.useCallback(() => setDragging(false), []);
172
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
+
173
289
  return imageValue ? (
174
290
  <div
175
291
  className="image-upload-widget-image"
@@ -178,15 +294,20 @@ const UnconnectedImageInput = (props) => {
178
294
  role="toolbar"
179
295
  >
180
296
  {selected && <ImageToolbar {...props} />}
181
- <img
182
- className={props.className}
183
- src={
184
- isInternalURL(imageValue)
185
- ? `${flattenToAppURL(imageValue)}/@@images/image/${imageSize}`
186
- : imageValue
187
- }
188
- alt=""
189
- />
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
+ )}
190
311
  </div>
191
312
  ) : (
192
313
  <div
@@ -227,7 +348,7 @@ const UnconnectedImageInput = (props) => {
227
348
  </Loader>
228
349
  </Dimmer>
229
350
  )}
230
- <img src={imageBlockSVG} alt="" className="placeholder" />
351
+ <Image src={imageBlockSVG} alt="" className="placeholder" />
231
352
  <p>{description || intl.formatMessage(messages.addImage)}</p>
232
353
  <div className="toolbar-wrapper">
233
354
  <div className="toolbar-inner" ref={linkEditor.anchorNode}>
@@ -242,15 +363,24 @@ const UnconnectedImageInput = (props) => {
242
363
  e.preventDefault();
243
364
  openObjectBrowser({
244
365
  mode: objectBrowserPickerType,
245
- onSelectItem: onSelectItem
246
- ? onSelectItem
247
- : (url, { title, image_field, image_scales }) => {
248
- onChange(props.id, flattenToAppURL(url), {
249
- title,
250
- image_field,
251
- image_scales,
252
- });
253
- },
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
+ },
254
384
  currentPath: contextUrl,
255
385
  });
256
386
  }}
@@ -311,13 +441,14 @@ const UnconnectedImageInput = (props) => {
311
441
  intl.formatMessage(messages.linkAnImage)
312
442
  }
313
443
  objectBrowserPickerType={objectBrowserPickerType}
314
- onChange={(_, e) =>
315
- onChange(
316
- props.id,
317
- isInternalURL(e) ? flattenToAppURL(e) : e,
318
- {},
319
- )
320
- }
444
+ onChange={(_, e) => {
445
+ onSubmitURL(e);
446
+ // onChange(
447
+ // props.id,
448
+ // isInternalURL(e) ? flattenToAppURL(e) : e,
449
+ // {},
450
+ // );
451
+ }}
321
452
  id={id}
322
453
  />
323
454
  )}
@@ -331,6 +462,8 @@ const UnconnectedImageInput = (props) => {
331
462
  };
332
463
 
333
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,
334
467
  connect(
335
468
  (state, ownProps) => {
336
469
  const requestId = `image-upload-${ownProps.id}`;
@@ -339,9 +472,9 @@ export const ImageInput = compose(
339
472
  content: state.content.subrequests[ownProps.block || requestId]?.data,
340
473
  };
341
474
  },
342
- { createContent },
475
+ { createContent, searchContent },
343
476
  ),
344
- )(withObjectBrowser(UnconnectedImageInput));
477
+ )(UnconnectedImageInput);
345
478
 
346
479
  const ImageUploadWidget = (props) => {
347
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"
@@ -82,6 +82,7 @@ export class ObjectBrowserWidgetComponent extends Component {
82
82
  openObjectBrowser: PropTypes.func.isRequired,
83
83
  allowExternals: PropTypes.bool,
84
84
  placeholder: PropTypes.string,
85
+ onlyFolderishSelectable: PropTypes.bool,
85
86
  };
86
87
 
87
88
  /**
@@ -98,6 +99,7 @@ export class ObjectBrowserWidgetComponent extends Component {
98
99
  return: 'multiple',
99
100
  initialPath: '',
100
101
  allowExternals: false,
102
+ onlyFolderishSelectable: false,
101
103
  };
102
104
 
103
105
  state = {
@@ -315,6 +317,9 @@ export class ObjectBrowserWidgetComponent extends Component {
315
317
  maximumSelectionSize:
316
318
  this.props.widgetOptions?.pattern_options?.maximumSelectionSize ||
317
319
  this.props.maximumSelectionSize,
320
+ onlyFolderishSelectable:
321
+ this.props.widgetOptions?.pattern_options?.onlyFolderishSelectable ||
322
+ this.props.onlyFolderishSelectable,
318
323
  });
319
324
  };
320
325
 
@@ -399,6 +404,7 @@ export class ObjectBrowserWidgetComponent extends Component {
399
404
  {this.state.manualLinkInput && isEmpty(items) && (
400
405
  <Button.Group>
401
406
  <Button
407
+ type="button"
402
408
  basic
403
409
  className="cancel"
404
410
  onClick={(e) => {
@@ -409,6 +415,7 @@ export class ObjectBrowserWidgetComponent extends Component {
409
415
  <Icon name={clearSVG} size="18px" color="#e40166" />
410
416
  </Button>
411
417
  <Button
418
+ type="button"
412
419
  basic
413
420
  primary
414
421
  disabled={!this.state.validURL}
@@ -423,6 +430,7 @@ export class ObjectBrowserWidgetComponent extends Component {
423
430
  )}
424
431
  {!this.state.manualLinkInput && (
425
432
  <Button
433
+ type="button"
426
434
  aria-label={this.props.intl.formatMessage(
427
435
  messages.openObjectBrowser,
428
436
  )}
@@ -4,17 +4,8 @@ import { render } from '@testing-library/react';
4
4
  import configureStore from 'redux-mock-store';
5
5
  import ObjectListWidget from './ObjectListWidget';
6
6
 
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
- });
17
-
7
+ vi.mock('@plone/volto/helpers/Loadable/Loadable');
8
+ vi.mock('@plone/volto/components/manage/Form');
18
9
  beforeAll(async () => {
19
10
  const { __setLoadables } = await import(
20
11
  '@plone/volto/helpers/Loadable/Loadable'
@@ -5,11 +5,7 @@ import { Provider } from 'react-intl-redux';
5
5
  import { render, fireEvent } from '@testing-library/react';
6
6
  import ObjectWidget from './ObjectWidget';
7
7
 
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
- });
8
+ vi.mock('@plone/volto/components/manage/Form');
13
9
 
14
10
  const mockStore = configureStore();
15
11
 
@@ -15,8 +15,12 @@ import groupBy from 'lodash/groupBy';
15
15
  import isEmpty from 'lodash/isEmpty';
16
16
  import map from 'lodash/map';
17
17
  import { defineMessages, injectIntl } from 'react-intl';
18
+ import { withRouter } from 'react-router';
18
19
  import { getQuerystring } from '@plone/volto/actions/querystring/querystring';
20
+ import { getQueryStringResults } from '@plone/volto/actions/querystringsearch/querystringsearch';
19
21
  import Icon from '@plone/volto/components/theme/Icon/Icon';
22
+ import ObjectBrowserWidget from '@plone/volto/components/manage/Widgets/ObjectBrowserWidget';
23
+ import NumberWidget from '@plone/volto/components/manage/Widgets/NumberWidget';
20
24
  import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
21
25
  import cx from 'classnames';
22
26
  import config from '@plone/volto/registry';
@@ -43,8 +47,27 @@ const messages = defineMessages({
43
47
  id: 'querystring-widget-select',
44
48
  defaultMessage: 'Select…',
45
49
  },
50
+ currentPath: {
51
+ id: 'query-widget-currentPath',
52
+ defaultMessage: 'Current path (./)',
53
+ },
54
+ parentPath: {
55
+ id: 'query-widget-parentPath',
56
+ defaultMessage: 'Parent path (../)',
57
+ },
46
58
  });
47
59
 
60
+ const parseUidDepth = (val) => {
61
+ if (typeof val !== 'string') return { uid: '', depth: 1 };
62
+ const lastSep = String(val).lastIndexOf('::');
63
+ if (lastSep !== -1) {
64
+ const uid = val.substring(0, lastSep);
65
+ const parsed = parseInt(val.substring(lastSep + 2), 10);
66
+ return { uid, depth: Number.isNaN(parsed) ? 1 : parsed };
67
+ }
68
+ return { uid: val, depth: 1 };
69
+ };
70
+
48
71
  /**
49
72
  * Widget for a querystring value, to define a catalog search criteria.
50
73
  */
@@ -97,6 +120,7 @@ export class QuerystringWidgetComponent extends Component {
97
120
  };
98
121
  this.onChangeValue = this.onChangeValue.bind(this);
99
122
  this.getWidget = this.getWidget.bind(this);
123
+ this.loadReferenceWidgetItem = this.loadReferenceWidgetItem.bind(this);
100
124
  }
101
125
 
102
126
  /**
@@ -111,6 +135,27 @@ export class QuerystringWidgetComponent extends Component {
111
135
  this.props.getQuerystring();
112
136
  }
113
137
 
138
+ loadReferenceWidgetItem(v) {
139
+ const loading =
140
+ this.props.reference[`${v}_query_reference`]?.loading ?? false;
141
+ if (!loading && v?.length > 0) {
142
+ this.props.getQueryStringResults(
143
+ '/',
144
+ {
145
+ b_size: 1,
146
+ query: [
147
+ {
148
+ i: 'path',
149
+ o: 'plone.app.querystring.operation.string.absolutePath',
150
+ v: v + '::0',
151
+ },
152
+ ],
153
+ },
154
+ v + '_query_reference',
155
+ );
156
+ }
157
+ }
158
+
114
159
  /**
115
160
  * Get correct widget
116
161
  * @method getWidget
@@ -118,15 +163,16 @@ export class QuerystringWidgetComponent extends Component {
118
163
  * @param {number} index Row index.
119
164
  * @returns {Object} Widget.
120
165
  */
121
- getWidget(row, index, Select) {
166
+ getWidget(row, index, Select, intl) {
122
167
  const props = {
123
168
  fluid: true,
124
169
  value: row.v,
125
170
  onChange: (data) => this.onChangeValue(index, data.target.value),
126
171
  };
127
172
  const values = this.props.indexes[row.i].values;
173
+ const operator = this.props.indexes[row.i].operators[row.o];
128
174
 
129
- switch (this.props.indexes[row.i].operators[row.o].widget) {
175
+ switch (operator.widget) {
130
176
  case null:
131
177
  return <span />;
132
178
  case 'DateWidget':
@@ -217,13 +263,93 @@ export class QuerystringWidgetComponent extends Component {
217
263
  </Form.Field>
218
264
  );
219
265
  case 'ReferenceWidget':
266
+ const { uid: uidValue, depth: depthValue } = parseUidDepth(props.value);
267
+ if (!this.props.reference[`${uidValue}_query_reference`]) {
268
+ this.loadReferenceWidgetItem(uidValue);
269
+ }
270
+ const referenceItem = this.props.reference[
271
+ `${uidValue}_query_reference`
272
+ ]
273
+ ? this.props.reference[`${uidValue}_query_reference`].items[0]
274
+ : null;
275
+ return (
276
+ <div className="location-object-browser">
277
+ <Form.Field className="object-browser-field">
278
+ <ObjectBrowserWidget
279
+ id={`query-reference-widget-${index}`}
280
+ mode="link"
281
+ onChange={(id, data) => {
282
+ const itemSelected = data.length > 0 ? data[0] : {};
283
+ const uid = itemSelected.UID ?? '';
284
+ this.onChangeValue(index, uid ? `${uid}::${depthValue}` : '');
285
+ this.loadReferenceWidgetItem(uid);
286
+ }}
287
+ value={uidValue && this.props.reference ? [referenceItem] : []}
288
+ wrapped={false}
289
+ onlyFolderishSelectable={true}
290
+ allowExternals={true}
291
+ />
292
+ </Form.Field>
293
+
294
+ {uidValue && (
295
+ <Form.Field className="reference-widget-depth">
296
+ <NumberWidget
297
+ title={intl.formatMessage({
298
+ id: 'Depth',
299
+ defaultMessage: 'Depth',
300
+ })}
301
+ min={1}
302
+ step={1}
303
+ value={depthValue}
304
+ onChange={(id, value) => {
305
+ const newDepth = parseInt(value, 10) || 1;
306
+ const curUid = uidValue || '';
307
+ this.onChangeValue(index, `${curUid}::${newDepth}`);
308
+ }}
309
+ />
310
+ </Form.Field>
311
+ )}
312
+ </div>
313
+ );
314
+ case 'RelativePathWidget':
315
+ const relativePathOptions = [
316
+ {
317
+ label: intl.formatMessage(messages.currentPath),
318
+ value: './',
319
+ },
320
+ {
321
+ label: intl.formatMessage(messages.parentPath),
322
+ value: '../',
323
+ },
324
+ ];
325
+ return (
326
+ <Form.Field style={{ flex: '1 0 auto', maxWidth: '92%' }}>
327
+ <Select
328
+ {...props}
329
+ className="react-select-container"
330
+ classNamePrefix="react-select"
331
+ options={relativePathOptions}
332
+ styles={customSelectStyles}
333
+ placeholder={this.props.intl.formatMessage(messages.select)}
334
+ theme={selectTheme}
335
+ components={{ DropdownIndicator, Option }}
336
+ onChange={(data) => {
337
+ this.onChangeValue(index, data.value);
338
+ }}
339
+ isMulti={false}
340
+ value={
341
+ relativePathOptions.filter((p) => p.value === props.value)?.[0]
342
+ }
343
+ />
344
+ </Form.Field>
345
+ );
220
346
  default:
221
347
  // if (row.o === 'plone.app.querystring.operation.string.relativePath') {
222
348
  // props.onChange = data => this.onChangeValue(index, data.target.value);
223
349
  // }
224
350
  return (
225
351
  <Form.Field style={{ flex: '1 0 auto' }}>
226
- <Input {...props} />
352
+ <Input {...props} description={operator.description} />
227
353
  </Form.Field>
228
354
  );
229
355
  }
@@ -334,7 +460,7 @@ export class QuerystringWidgetComponent extends Component {
334
460
  value: row.i,
335
461
  label: indexes[row.i]?.title,
336
462
  }}
337
- onChange={(data) =>
463
+ onChange={(data) => {
338
464
  onChange(
339
465
  id,
340
466
  map(value, (curRow, curIndex) =>
@@ -346,8 +472,8 @@ export class QuerystringWidgetComponent extends Component {
346
472
  }
347
473
  : curRow,
348
474
  ),
349
- )
350
- }
475
+ );
476
+ }}
351
477
  />
352
478
  </Form.Field>
353
479
  <Form.Field style={{ flex: '1 0 auto' }}>
@@ -408,7 +534,7 @@ export class QuerystringWidgetComponent extends Component {
408
534
  </Button>
409
535
  )}
410
536
  </div>
411
- {this.getWidget(row, index, Select)}
537
+ {this.getWidget(row, index, Select, intl)}
412
538
  {this.props.indexes[row.i].operators[row.o].widget && (
413
539
  <Button
414
540
  onClick={(event) => {
@@ -500,10 +626,12 @@ export class QuerystringWidgetComponent extends Component {
500
626
  export default compose(
501
627
  injectIntl,
502
628
  injectLazyLibs(['reactSelect']),
629
+ withRouter,
503
630
  connect(
504
- (state) => ({
631
+ (state, props) => ({
505
632
  indexes: state.querystring.indexes,
633
+ reference: state.querystringsearch.subrequests,
506
634
  }),
507
- { getQuerystring },
635
+ { getQuerystring, getQueryStringResults },
508
636
  ),
509
637
  )(QuerystringWidgetComponent);
@@ -7,12 +7,7 @@ import RadioGroupWidget from './RadioGroupWidget';
7
7
 
8
8
  const mockStore = configureStore();
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
- });
15
-
10
+ vi.mock('@plone/volto/helpers/Loadable/Loadable');
16
11
  beforeAll(async () => {
17
12
  const { __setLoadables } = await import(
18
13
  '@plone/volto/helpers/Loadable/Loadable'