@plone/volto 17.0.0-alpha.2 → 17.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/CHANGELOG.md +549 -15
  3. package/CONTRIBUTING.md +1 -1
  4. package/README.md +11 -14
  5. package/addon-registry.js +34 -0
  6. package/create-theme-addons-loader.js +79 -0
  7. package/cypress/support/commands.js +58 -5
  8. package/cypress/support/e2e.js +1 -2
  9. package/cypress/support/volto-slate.js +4 -5
  10. package/docker-compose.yml +1 -1
  11. package/locales/ca/LC_MESSAGES/volto.po +282 -7
  12. package/locales/ca.json +1 -1
  13. package/locales/de/LC_MESSAGES/volto.po +301 -26
  14. package/locales/de.json +1 -1
  15. package/locales/en/LC_MESSAGES/volto.po +281 -6
  16. package/locales/en.json +1 -1
  17. package/locales/es/LC_MESSAGES/volto.po +291 -16
  18. package/locales/es.json +1 -1
  19. package/locales/eu/LC_MESSAGES/volto.po +282 -7
  20. package/locales/eu.json +1 -1
  21. package/locales/fi/LC_MESSAGES/volto.po +4891 -0
  22. package/locales/fi.json +1 -1
  23. package/locales/fr/LC_MESSAGES/volto.po +282 -7
  24. package/locales/fr.json +1 -1
  25. package/locales/it/LC_MESSAGES/volto.po +284 -9
  26. package/locales/it.json +1 -1
  27. package/locales/ja/LC_MESSAGES/volto.po +282 -7
  28. package/locales/ja.json +1 -1
  29. package/locales/nl/LC_MESSAGES/volto.po +937 -650
  30. package/locales/nl.json +1 -1
  31. package/locales/pt/LC_MESSAGES/volto.po +282 -7
  32. package/locales/pt.json +1 -1
  33. package/locales/pt_BR/LC_MESSAGES/volto.po +291 -16
  34. package/locales/pt_BR.json +1 -1
  35. package/locales/ro/LC_MESSAGES/volto.po +282 -7
  36. package/locales/ro.json +1 -1
  37. package/locales/volto.pot +282 -7
  38. package/locales/zh_CN/LC_MESSAGES/volto.po +282 -7
  39. package/locales/zh_CN.json +1 -1
  40. package/package.json +8 -6
  41. package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +1 -1
  42. package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +1 -1
  43. package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +1 -1
  44. package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +1 -1
  45. package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +1 -1
  46. package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +1 -1
  47. package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +1 -1
  48. package/packages/volto-slate/build/messages/src/elementEditor/messages.json +1 -1
  49. package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +1 -1
  50. package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +1 -1
  51. package/packages/volto-slate/package.json +1 -1
  52. package/packages/volto-slate/src/actions/index.js +1 -1
  53. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.jsx +21 -212
  54. package/packages/volto-slate/src/blocks/Table/schema.js +122 -0
  55. package/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx +8 -3
  56. package/packages/volto-slate/src/blocks/Text/SlashMenu.jsx +4 -3
  57. package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +20 -16
  58. package/packages/volto-slate/src/blocks/Text/extensions/withDeserializers.js +3 -1
  59. package/packages/volto-slate/src/blocks/Text/index.js +10 -2
  60. package/packages/volto-slate/src/editor/config.jsx +5 -4
  61. package/packages/volto-slate/src/editor/deserialize.js +0 -1
  62. package/packages/volto-slate/src/editor/index.js +4 -4
  63. package/packages/volto-slate/src/editor/less/slate.less +28 -0
  64. package/packages/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx +14 -4
  65. package/packages/volto-slate/src/editor/plugins/StyleMenu/utils.js +14 -5
  66. package/packages/volto-slate/src/editor/render.jsx +68 -8
  67. package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +2 -2
  68. package/packages/volto-slate/src/editor/ui/index.js +15 -15
  69. package/packages/volto-slate/src/index.js +2 -2
  70. package/packages/volto-slate/src/utils/blocks.js +7 -0
  71. package/packages/volto-slate/src/widgets/RichTextWidget.jsx +15 -8
  72. package/razzle.config.js +28 -0
  73. package/src/actions/index.js +6 -0
  74. package/src/actions/language/language.js +9 -8
  75. package/src/actions/querystringsearch/querystringsearch.js +20 -14
  76. package/src/actions/relations/rebuild.js +25 -0
  77. package/src/actions/relations/relations.js +86 -0
  78. package/src/actions/relations/relations.test.js +15 -0
  79. package/src/components/index.js +3 -0
  80. package/src/components/manage/Add/Add.jsx +2 -2
  81. package/src/components/manage/AnchorPlugin/index.jsx +2 -2
  82. package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +3 -1
  83. package/src/components/manage/BlockChooser/BlockChooser.jsx +14 -5
  84. package/src/components/manage/BlockChooser/BlockChooser.test.jsx +5 -0
  85. package/src/components/manage/Blocks/Block/BlocksForm.jsx +19 -2
  86. package/src/components/manage/Blocks/Block/Edit.jsx +1 -1
  87. package/src/components/manage/Blocks/Block/Style.jsx +2 -2
  88. package/src/components/manage/Blocks/Container/Data.jsx +32 -0
  89. package/src/components/manage/Blocks/Container/Edit.jsx +174 -0
  90. package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +120 -0
  91. package/src/components/manage/Blocks/Container/NewBlockAddButton.jsx +84 -0
  92. package/src/components/manage/Blocks/Container/SimpleContainerToolbar.jsx +54 -0
  93. package/src/components/manage/Blocks/Grid/Edit.jsx +33 -0
  94. package/src/components/manage/Blocks/Grid/View.jsx +43 -0
  95. package/src/components/manage/Blocks/Grid/adapter.js +14 -0
  96. package/src/components/manage/Blocks/Grid/grid-1.svg +6 -0
  97. package/src/components/manage/Blocks/Grid/grid-2.svg +9 -0
  98. package/src/components/manage/Blocks/Grid/grid-3.svg +10 -0
  99. package/src/components/manage/Blocks/Grid/grid-4.svg +11 -0
  100. package/src/components/manage/Blocks/Grid/schema.js +35 -0
  101. package/src/components/manage/Blocks/Grid/templates.js +47 -0
  102. package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +6 -1
  103. package/src/components/manage/Blocks/Image/Edit.jsx +51 -12
  104. package/src/components/manage/Blocks/Image/Edit.test.jsx +2 -0
  105. package/src/components/manage/Blocks/Image/ImageSidebar.jsx +66 -16
  106. package/src/components/manage/Blocks/Image/View.jsx +25 -5
  107. package/src/components/manage/Blocks/Image/View.test.jsx +20 -0
  108. package/src/components/manage/Blocks/Image/schema.js +12 -9
  109. package/src/components/manage/Blocks/Image/utils.js +14 -0
  110. package/src/components/manage/Blocks/LeadImage/Edit.jsx +32 -10
  111. package/src/components/manage/Blocks/LeadImage/Edit.test.jsx +11 -1
  112. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +28 -9
  113. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -2
  114. package/src/components/manage/Blocks/LeadImage/View.jsx +50 -38
  115. package/src/components/manage/Blocks/LeadImage/View.test.jsx +11 -1
  116. package/src/components/manage/Blocks/Listing/DefaultTemplate.jsx +18 -3
  117. package/src/components/manage/Blocks/Listing/Edit.jsx +0 -14
  118. package/src/components/manage/Blocks/Listing/ListingBody.jsx +30 -8
  119. package/src/components/manage/Blocks/Listing/ListingBody.test.jsx +20 -0
  120. package/src/components/manage/Blocks/Listing/SummaryTemplate.jsx +1 -1
  121. package/src/components/manage/Blocks/Listing/getAsyncData.js +9 -3
  122. package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +26 -18
  123. package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +5 -4
  124. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +2 -1
  125. package/src/components/manage/Blocks/Search/components/DateRangeFacet.jsx +4 -1
  126. package/src/components/manage/Blocks/Search/components/Facets.jsx +64 -4
  127. package/src/components/manage/Blocks/Search/components/SearchInput.jsx +9 -2
  128. package/src/components/manage/Blocks/Search/components/index.js +13 -13
  129. package/src/components/manage/Blocks/Search/hocs/index.js +2 -2
  130. package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +2 -2
  131. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +43 -15
  132. package/src/components/manage/Blocks/Search/layout/LeftColumnFacets.jsx +17 -5
  133. package/src/components/manage/Blocks/Search/layout/RightColumnFacets.jsx +17 -5
  134. package/src/components/manage/Blocks/Search/layout/TopSideFacets.jsx +21 -5
  135. package/src/components/manage/Blocks/Search/schema.js +16 -1
  136. package/src/components/manage/Blocks/Teaser/Body.jsx +0 -1
  137. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +5 -10
  138. package/src/components/manage/Blocks/Teaser/schema.js +5 -0
  139. package/src/components/manage/Blocks/Title/View.jsx +15 -5
  140. package/src/components/manage/Blocks/Title/View.test.jsx +16 -1
  141. package/src/components/manage/Blocks/ToC/Schema.jsx +5 -1
  142. package/src/components/manage/Blocks/ToC/View.jsx +8 -1
  143. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +17 -4
  144. package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +148 -10
  145. package/src/components/manage/Blocks/ToC/variations/index.js +3 -1
  146. package/src/components/manage/Contents/Contents.jsx +47 -32
  147. package/src/components/manage/Contents/ContentsItem.jsx +6 -0
  148. package/src/components/manage/Contents/ContentsUploadModal.jsx +10 -5
  149. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +3 -3
  150. package/src/components/manage/Controlpanels/Controlpanels.jsx +199 -224
  151. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +46 -7
  152. package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +66 -0
  153. package/src/components/manage/Controlpanels/Relations/Relations.jsx +114 -0
  154. package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +479 -0
  155. package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +531 -0
  156. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.jsx +3 -3
  157. package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +51 -82
  158. package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +79 -75
  159. package/src/components/manage/DragDropList/DragDropList.jsx +18 -13
  160. package/src/components/manage/Form/Form.jsx +5 -3
  161. package/src/components/manage/Form/InlineForm.jsx +39 -9
  162. package/src/components/manage/Form/InlineFormState.js +8 -0
  163. package/src/components/manage/History/History.jsx +11 -1
  164. package/src/components/manage/LinksToItem/LinksToItem.jsx +209 -0
  165. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +97 -0
  166. package/src/components/manage/Multilingual/CreateTranslation.jsx +2 -2
  167. package/src/components/manage/Multilingual/TranslationObject.jsx +4 -3
  168. package/src/components/manage/Preferences/ChangePassword.jsx +2 -2
  169. package/src/components/manage/Preferences/PersonalPreferences.jsx +2 -2
  170. package/src/components/manage/Sharing/Sharing.jsx +5 -1
  171. package/src/components/manage/Sidebar/AlignBlock.jsx +1 -1
  172. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +38 -0
  173. package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +34 -0
  174. package/src/components/manage/TemplateChooser/template.svg +10 -0
  175. package/src/components/manage/Toast/Toast.jsx +2 -2
  176. package/src/components/manage/Toolbar/More.jsx +15 -0
  177. package/src/components/manage/Toolbar/Types.jsx +2 -2
  178. package/src/components/manage/UniversalLink/UniversalLink.jsx +2 -6
  179. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +36 -0
  180. package/src/components/manage/Widgets/ColorPickerWidget.jsx +6 -1
  181. package/src/components/manage/Widgets/DatetimeWidget.jsx +9 -5
  182. package/src/components/manage/Widgets/FileWidget.jsx +2 -1
  183. package/src/components/manage/Widgets/ObjectListWidget.jsx +3 -8
  184. package/src/components/manage/Widgets/RecurrenceWidget/ByDayField.jsx +2 -1
  185. package/src/components/manage/Widgets/RecurrenceWidget/MonthOfTheYearField.jsx +2 -1
  186. package/src/components/manage/Widgets/RecurrenceWidget/Occurences.jsx +2 -1
  187. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +8 -3
  188. package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthField.jsx +2 -1
  189. package/src/components/manage/Widgets/SelectUtils.js +1 -1
  190. package/src/components/manage/Widgets/SelectWidget.jsx +1 -1
  191. package/src/components/theme/Anontools/Anontools.jsx +44 -72
  192. package/src/components/theme/Anontools/Anontools.stories.jsx +16 -6
  193. package/src/components/theme/Anontools/Anontools.test.jsx +16 -2
  194. package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +52 -99
  195. package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.jsx +14 -13
  196. package/src/components/theme/Comments/CommentEditModal.jsx +63 -115
  197. package/src/components/theme/Component/Component.jsx +1 -1
  198. package/src/components/theme/ContactForm/ContactForm.jsx +108 -192
  199. package/src/components/theme/ContactForm/ContactForm.stories.jsx +1 -1
  200. package/src/components/theme/ContactForm/ContactForm.test.jsx +2 -3
  201. package/src/components/theme/Footer/Footer.jsx +2 -13
  202. package/src/components/theme/Header/Header.jsx +37 -63
  203. package/src/components/theme/Header/Header.test.jsx +18 -0
  204. package/src/components/theme/Icon/Icon.jsx +2 -2
  205. package/src/components/theme/Image/Image.jsx +96 -0
  206. package/src/components/theme/Image/Image.test.jsx +125 -0
  207. package/src/components/theme/LanguageSelector/LanguageSelector.js +8 -3
  208. package/src/components/theme/Login/Login.jsx +1 -0
  209. package/src/components/theme/Logo/Logo.jsx +4 -1
  210. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +2 -2
  211. package/src/components/theme/Navigation/NavItem.jsx +4 -2
  212. package/src/components/theme/NotFound/NotFound.jsx +55 -41
  213. package/src/components/theme/PasswordReset/PasswordReset.jsx +7 -4
  214. package/src/components/theme/PasswordReset/RequestPasswordReset.jsx +1 -1
  215. package/src/components/theme/PreviewImage/PreviewImage.jsx +25 -14
  216. package/src/components/theme/PreviewImage/PreviewImage.test.js +39 -16
  217. package/src/components/theme/SearchWidget/SearchWidget.jsx +38 -98
  218. package/src/components/theme/Sitemap/Sitemap.jsx +5 -3
  219. package/src/components/theme/View/AlbumView.jsx +20 -16
  220. package/src/components/theme/View/DefaultView.jsx +1 -1
  221. package/src/components/theme/View/EventDatesInfo.jsx +2 -1
  222. package/src/components/theme/View/EventView.jsx +36 -25
  223. package/src/components/theme/View/FileView.jsx +23 -18
  224. package/src/components/theme/View/ImageView.jsx +40 -32
  225. package/src/components/theme/View/ImageView.test.jsx +4 -0
  226. package/src/components/theme/View/LinkView.jsx +53 -78
  227. package/src/components/theme/View/ListingView.jsx +36 -28
  228. package/src/components/theme/View/NewsItemView.jsx +16 -17
  229. package/src/components/theme/View/RenderBlocks.jsx +56 -21
  230. package/src/components/theme/View/RenderEmptyBlock.jsx +5 -0
  231. package/src/components/theme/View/SummaryView.jsx +49 -39
  232. package/src/components/theme/View/TabularView.jsx +59 -53
  233. package/src/components/theme/Widgets/DateWidget.jsx +2 -1
  234. package/src/components/theme/Widgets/DatetimeWidget.jsx +2 -1
  235. package/src/components/theme/Widgets/RelationsWidget.jsx +13 -11
  236. package/src/config/Blocks.jsx +46 -0
  237. package/src/config/Components.jsx +2 -1
  238. package/src/config/ControlPanels.js +2 -0
  239. package/src/config/NonContentRoutes.jsx +1 -0
  240. package/src/config/RichTextEditor/Blocks.jsx +2 -2
  241. package/src/config/RichTextEditor/FromHTML.jsx +2 -2
  242. package/src/config/RichTextEditor/Styles.jsx +1 -1
  243. package/src/config/Widgets.jsx +2 -0
  244. package/src/config/index.js +24 -0
  245. package/src/config/server.js +2 -0
  246. package/src/constants/ActionTypes.js +4 -0
  247. package/src/constants/Indexes.js +3 -1
  248. package/src/constants/Languages.js +8 -4
  249. package/src/express-middleware/devproxy.js +1 -1
  250. package/src/express-middleware/files.js +3 -3
  251. package/src/express-middleware/images.js +4 -4
  252. package/src/express-middleware/ok.js +16 -0
  253. package/src/express-middleware/robotstxt.js +1 -1
  254. package/src/express-middleware/sitemap.js +37 -5
  255. package/src/express-middleware/static.js +3 -3
  256. package/src/helpers/Api/Api.js +1 -1
  257. package/src/helpers/Blocks/Blocks.js +48 -0
  258. package/src/helpers/Blocks/Blocks.test.js +79 -0
  259. package/src/helpers/Extensions/index.js +2 -1
  260. package/src/helpers/Extensions/withBlockSchemaEnhancer.js +15 -11
  261. package/src/helpers/Extensions/withBlockSchemaEnhancer.test.js +145 -0
  262. package/src/helpers/FormValidation/FormValidation.js +40 -2
  263. package/src/helpers/FormValidation/FormValidation.test.js +73 -0
  264. package/src/helpers/Html/Html.jsx +3 -1
  265. package/src/helpers/Html/Html.test.jsx +5 -0
  266. package/src/helpers/MessageLabels/MessageLabels.js +80 -0
  267. package/src/helpers/Robots/Robots.js +24 -6
  268. package/src/helpers/ScrollToTop/ScrollToTop.jsx +5 -3
  269. package/src/helpers/Sitemap/Sitemap.js +44 -2
  270. package/src/helpers/Url/Url.js +49 -7
  271. package/src/helpers/Url/Url.test.js +67 -0
  272. package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +191 -0
  273. package/src/helpers/Utils/Utils.js +63 -13
  274. package/src/helpers/Utils/Utils.test.js +4 -4
  275. package/src/helpers/Utils/usePagination.js +67 -14
  276. package/src/helpers/Utils/usePagination.test.js +115 -0
  277. package/src/helpers/index.js +20 -10
  278. package/src/hooks/client/useClient.js +11 -0
  279. package/src/hooks/clipboard/useClipboard.js +26 -0
  280. package/src/hooks/index.js +2 -0
  281. package/src/icons/grid-block.svg +11 -0
  282. package/src/middleware/Api.test.js +54 -0
  283. package/src/middleware/api.js +24 -6
  284. package/src/middleware/index.js +2 -2
  285. package/src/reducers/actions/actions.js +8 -6
  286. package/src/reducers/actions/actions.test.js +70 -0
  287. package/src/reducers/breadcrumbs/breadcrumbs.js +1 -1
  288. package/src/reducers/index.js +2 -0
  289. package/src/reducers/navigation/navigation.js +1 -1
  290. package/src/reducers/relations/relations.js +173 -0
  291. package/src/reducers/types/types.js +1 -1
  292. package/src/routes.js +14 -0
  293. package/src/server.jsx +28 -23
  294. package/src/start-server.js +2 -2
  295. package/test-setup-config.js +11 -1
  296. package/theme/themes/pastanaga/extras/blocks.less +5 -1
  297. package/theme/themes/pastanaga/extras/contents.less +1 -0
  298. package/theme/themes/pastanaga/extras/grid.less +426 -0
  299. package/theme/themes/pastanaga/extras/main.less +8 -1
  300. package/theme/themes/pastanaga/extras/search.less +6 -0
  301. package/theme/themes/pastanaga/extras/sidebar.less +4 -0
  302. package/theme/themes/pastanaga/extras/toc.less +29 -0
  303. package/theme/themes/pastanaga/extras/userscontrolpanel.less +99 -76
  304. package/.changelog.draft +0 -31
  305. package/.editorconfig +0 -36
  306. package/.storybook/main.js +0 -127
  307. package/.storybook/manager.js +0 -15
  308. package/.storybook/preview.js +0 -21
  309. package/.storybook/static/previewImage.svg +0 -48
  310. package/.yarnrc.yml +0 -5
  311. package/jsdoc.json +0 -16
  312. package/netlify.toml +0 -5
  313. package/pyvenv.cfg +0 -3
  314. package/share/man/man1/ttx.1 +0 -225
  315. package/src/components/manage/Blocks/Teaser/utils.js +0 -44
  316. package/src/components/manage/Blocks/Teaser/utils.test.jsx +0 -229
  317. package/src/components/theme/Header/Header.md +0 -27
  318. package/towncrier.toml +0 -33
@@ -1,12 +1,6 @@
1
- /**
2
- * Header component.
3
- * @module components/theme/Header/Header
4
- */
5
-
6
- import React, { Component } from 'react';
7
1
  import { Container, Segment } from 'semantic-ui-react';
8
2
  import PropTypes from 'prop-types';
9
- import { connect } from 'react-redux';
3
+ import { useSelector, shallowEqual } from 'react-redux';
10
4
 
11
5
  import {
12
6
  Anontools,
@@ -16,65 +10,45 @@ import {
16
10
  SearchWidget,
17
11
  } from '@plone/volto/components';
18
12
 
19
- /**
20
- * Header component class.
21
- * @class Header
22
- * @extends Component
23
- */
24
- class Header extends Component {
25
- /**
26
- * Property types.
27
- * @property {Object} propTypes Property types.
28
- * @static
29
- */
30
- static propTypes = {
31
- token: PropTypes.string,
32
- pathname: PropTypes.string.isRequired,
33
- };
34
-
35
- /**
36
- * Default properties.
37
- * @property {Object} defaultProps Default properties.
38
- * @static
39
- */
40
- static defaultProps = {
41
- token: null,
42
- };
13
+ const Header = ({ pathname }) => {
14
+ const token = useSelector((state) => state.userSession.token, shallowEqual);
43
15
 
44
- /**
45
- * Render method.
46
- * @method render
47
- * @returns {string} Markup for the component.
48
- */
49
- render() {
50
- return (
51
- <Segment basic className="header-wrapper" role="banner">
52
- <Container>
53
- <div className="header">
54
- <div className="logo-nav-wrapper">
55
- <div className="logo">
56
- <Logo />
57
- </div>
58
- <Navigation pathname={this.props.pathname} />
16
+ return (
17
+ <Segment basic className="header-wrapper" role="banner">
18
+ <Container>
19
+ <div className="header">
20
+ <div className="logo-nav-wrapper">
21
+ <div className="logo">
22
+ <Logo />
59
23
  </div>
60
- <div className="tools-search-wrapper">
61
- <LanguageSelector />
62
- {!this.props.token && (
63
- <div className="tools">
64
- <Anontools />
65
- </div>
66
- )}
67
- <div className="search">
68
- <SearchWidget />
24
+ <Navigation pathname={pathname} />
25
+ </div>
26
+ <div className="tools-search-wrapper">
27
+ <LanguageSelector />
28
+ {!token && (
29
+ <div className="tools">
30
+ <Anontools />
69
31
  </div>
32
+ )}
33
+ <div className="search">
34
+ <SearchWidget />
70
35
  </div>
71
36
  </div>
72
- </Container>
73
- </Segment>
74
- );
75
- }
76
- }
37
+ </div>
38
+ </Container>
39
+ </Segment>
40
+ );
41
+ };
42
+
43
+ export default Header;
44
+
45
+ Header.propTypes = {
46
+ token: PropTypes.string,
47
+ pathname: PropTypes.string.isRequired,
48
+ content: PropTypes.objectOf(PropTypes.any),
49
+ };
77
50
 
78
- export default connect((state) => ({
79
- token: state.userSession.token,
80
- }))(Header);
51
+ Header.defaultProps = {
52
+ token: null,
53
+ content: null,
54
+ };
@@ -39,4 +39,22 @@ describe('Header', () => {
39
39
  const json = component.toJSON();
40
40
  expect(json).toMatchSnapshot();
41
41
  });
42
+
43
+ it('renders a header component - auth', () => {
44
+ const store = mockStore({
45
+ userSession: { token: '1234567890' },
46
+ intl: {
47
+ locale: 'en',
48
+ messages: {},
49
+ },
50
+ });
51
+
52
+ const component = renderer.create(
53
+ <Provider store={store}>
54
+ <Header pathname="/blog" />
55
+ </Provider>,
56
+ );
57
+ const json = component.toJSON();
58
+ expect(json).toMatchSnapshot();
59
+ });
42
60
  });
@@ -44,8 +44,8 @@ const Icon = ({
44
44
  ariaHidden,
45
45
  }) => (
46
46
  <svg
47
- xmlns={name.attributes && name.attributes.xmlns}
48
- viewBox={name.attributes && name.attributes.viewBox}
47
+ xmlns={name?.attributes?.xmlns}
48
+ viewBox={name?.attributes?.viewBox}
49
49
  style={{
50
50
  height: size,
51
51
  width: 'auto',
@@ -0,0 +1,96 @@
1
+ import PropTypes from 'prop-types';
2
+ import cx from 'classnames';
3
+ import { flattenToAppURL } from '@plone/volto/helpers';
4
+
5
+ /**
6
+ * Image component
7
+ * @param {object} item - Context item that has the image field (can also be a catalog brain or summary)
8
+ * @param {string} imageField - Key of the image field inside the item, or inside the image_scales object of the item if it is a catalog brain or summary
9
+ * @param {string} src - URL of the image to be used if the item field is not available
10
+ * @param {string} alt - Alternative text for the image
11
+ * @param {boolean} loading - (default: eager) set to `lazy` to lazy load the image
12
+ * @param {boolean} responsive - (default: false) set to `true` to add the `responsive` class to the image
13
+ * @param {string} className - Additional classes to add to the image
14
+ */
15
+ export default function Image({
16
+ item,
17
+ imageField,
18
+ src,
19
+ alt = '',
20
+ loading = 'eager',
21
+ responsive = false,
22
+ className = '',
23
+ ...imageProps
24
+ }) {
25
+ if (!item && !src) return null;
26
+
27
+ // TypeScript hints for editor autocomplete :)
28
+ /** @type {React.ImgHTMLAttributes<HTMLImageElement>} */
29
+ const attrs = {};
30
+
31
+ if (!item && src) {
32
+ attrs.src = src;
33
+ attrs.className = cx(className, { responsive });
34
+ } else {
35
+ const isFromRealObject = !item.image_scales;
36
+ const imageFieldWithDefault = imageField || item.image_field || 'image';
37
+
38
+ const image = isFromRealObject
39
+ ? item[imageFieldWithDefault]
40
+ : item.image_scales[imageFieldWithDefault]?.[0];
41
+
42
+ if (!image) return null;
43
+
44
+ const isSvg = image['content-type'] === 'image/svg+xml';
45
+
46
+ const baseUrl = isFromRealObject ? '' : flattenToAppURL(item['@id'] + '/');
47
+
48
+ attrs.src = `${baseUrl}${flattenToAppURL(image.download)}`;
49
+ attrs.width = image.width;
50
+ attrs.height = image.height;
51
+ attrs.style = {
52
+ aspectRatio: `${image.width} / ${image.height}`,
53
+ ...imageProps.style,
54
+ };
55
+ attrs.className = cx(className, { responsive });
56
+
57
+ if (!isSvg && image.scales && Object.keys(image.scales).length > 0) {
58
+ const sortedScales = Object.values(image.scales).sort((a, b) => {
59
+ if (a.width > b.width) return 1;
60
+ else if (a.width < b.width) return -1;
61
+ else return 0;
62
+ });
63
+
64
+ attrs.srcSet = sortedScales
65
+ .map(
66
+ (scale) =>
67
+ `${baseUrl}${flattenToAppURL(scale.download)} ${scale.width}w`,
68
+ )
69
+ .join(', ');
70
+ }
71
+ }
72
+
73
+ if (loading === 'lazy') {
74
+ attrs.loading = 'lazy';
75
+ attrs.decoding = 'async';
76
+ } else {
77
+ attrs.fetchpriority = 'high';
78
+ }
79
+
80
+ return <img {...attrs} alt={alt} {...imageProps} />;
81
+ }
82
+
83
+ Image.propTypes = {
84
+ item: PropTypes.shape({
85
+ '@id': PropTypes.string,
86
+ image_field: PropTypes.string,
87
+ image_scales: PropTypes.object,
88
+ image: PropTypes.object,
89
+ }),
90
+ imageField: PropTypes.string,
91
+ src: PropTypes.string,
92
+ alt: PropTypes.string.isRequired,
93
+ loading: PropTypes.string,
94
+ responsive: PropTypes.bool,
95
+ className: PropTypes.string,
96
+ };
@@ -0,0 +1,125 @@
1
+ import React from 'react';
2
+ import renderer from 'react-test-renderer';
3
+ import Image from './Image';
4
+
5
+ test('renders an image component with fetchpriority high', () => {
6
+ const component = renderer.create(
7
+ <Image
8
+ item={{
9
+ image: {
10
+ download: 'http://localhost:3000/image/@@images/image/image.png',
11
+ width: 400,
12
+ height: 400,
13
+ scales: {
14
+ preview: {
15
+ download:
16
+ 'http://localhost:3000/image/@@images/image/image-400.png',
17
+ width: 400,
18
+ height: 400,
19
+ },
20
+ },
21
+ },
22
+ }}
23
+ imageField="image"
24
+ alt="alt text"
25
+ />,
26
+ );
27
+ const json = component.toJSON();
28
+ expect(json).toMatchSnapshot();
29
+ });
30
+
31
+ test('renders an image component with lazy loading', () => {
32
+ const component = renderer.create(
33
+ <Image
34
+ item={{
35
+ image: {
36
+ download: 'http://localhost:3000/image/@@images/image/image.png',
37
+ width: 400,
38
+ height: 400,
39
+ scales: {
40
+ preview: {
41
+ download:
42
+ 'http://localhost:3000/image/@@images/image/image-400.png',
43
+ width: 400,
44
+ height: 400,
45
+ },
46
+ },
47
+ },
48
+ }}
49
+ imageField="image"
50
+ alt="alt text"
51
+ loading="lazy"
52
+ />,
53
+ );
54
+ const json = component.toJSON();
55
+ expect(json).toMatchSnapshot();
56
+ });
57
+
58
+ test('renders an image component with responsive class', () => {
59
+ const component = renderer.create(
60
+ <Image
61
+ item={{
62
+ image: {
63
+ download: 'http://localhost:3000/image/@@images/image/image.png',
64
+ width: 400,
65
+ height: 400,
66
+ scales: {
67
+ preview: {
68
+ download:
69
+ 'http://localhost:3000/image/@@images/image/image-400.png',
70
+ width: 400,
71
+ height: 400,
72
+ },
73
+ },
74
+ },
75
+ }}
76
+ imageField="image"
77
+ alt="alt text"
78
+ responsive={true}
79
+ />,
80
+ );
81
+ const json = component.toJSON();
82
+ expect(json).toMatchSnapshot();
83
+ });
84
+
85
+ test('renders an image component from a catalog brain', () => {
86
+ const component = renderer.create(
87
+ <Image
88
+ item={{
89
+ '@id': 'http://localhost:3000/image',
90
+ image_field: 'image',
91
+ image_scales: {
92
+ image: [
93
+ {
94
+ download: '@@images/image/image.png',
95
+ width: 400,
96
+ height: 400,
97
+ scales: {
98
+ preview: {
99
+ download: '@@images/image/image-400.png',
100
+ width: 400,
101
+ height: 400,
102
+ },
103
+ },
104
+ },
105
+ ],
106
+ },
107
+ }}
108
+ imageField="image"
109
+ alt="alt text"
110
+ />,
111
+ );
112
+ const json = component.toJSON();
113
+ expect(json).toMatchSnapshot();
114
+ });
115
+
116
+ test('renders an image component from a string src', () => {
117
+ const component = renderer.create(
118
+ <Image
119
+ src="http://localhost:3000/image/@@images/image/image.png"
120
+ alt="alt text"
121
+ />,
122
+ );
123
+ const json = component.toJSON();
124
+ expect(json).toMatchSnapshot();
125
+ });
@@ -11,7 +11,12 @@ import { useSelector } from 'react-redux';
11
11
  import cx from 'classnames';
12
12
  import { find, map } from 'lodash';
13
13
 
14
- import { Helmet, langmap, flattenToAppURL } from '@plone/volto/helpers';
14
+ import {
15
+ Helmet,
16
+ langmap,
17
+ flattenToAppURL,
18
+ toReactIntlLang,
19
+ } from '@plone/volto/helpers';
15
20
 
16
21
  import config from '@plone/volto/registry';
17
22
 
@@ -42,7 +47,7 @@ const LanguageSelector = (props) => {
42
47
  aria-label={`${intl.formatMessage(
43
48
  messages.switchLanguageTo,
44
49
  )} ${langmap[lang].nativeName.toLowerCase()}`}
45
- className={cx({ selected: lang === currentLang })}
50
+ className={cx({ selected: toReactIntlLang(lang) === currentLang })}
46
51
  to={translation ? flattenToAppURL(translation['@id']) : `/${lang}`}
47
52
  title={langmap[lang].nativeName}
48
53
  onClick={() => {
@@ -57,7 +62,7 @@ const LanguageSelector = (props) => {
57
62
  </div>
58
63
  ) : (
59
64
  <Helmet>
60
- <html lang={settings.defaultLanguage} />
65
+ <html lang={toReactIntlLang(settings.defaultLanguage)} />
61
66
  </Helmet>
62
67
  );
63
68
  };
@@ -239,6 +239,7 @@ class Login extends Component {
239
239
  <Input
240
240
  type="password"
241
241
  id="password"
242
+ autoComplete="current-password"
242
243
  name="password"
243
244
  placeholder={this.props.intl.formatMessage(
244
245
  messages.password,
@@ -8,6 +8,7 @@ import { Image } from 'semantic-ui-react';
8
8
  import { useSelector } from 'react-redux';
9
9
  import config from '@plone/volto/registry';
10
10
  import { UniversalLink } from '@plone/volto/components';
11
+ import { toBackendLang } from '@plone/volto/helpers';
11
12
  import LogoImage from '@plone/volto/components/theme/Logo/Logo.svg';
12
13
 
13
14
  const messages = defineMessages({
@@ -34,13 +35,15 @@ const Logo = () => {
34
35
 
35
36
  return (
36
37
  <UniversalLink
37
- href={settings.isMultilingual ? `/${lang}` : '/'}
38
+ href={settings.isMultilingual ? `/${toBackendLang(lang)}` : '/'}
38
39
  title={intl.formatMessage(messages.site)}
39
40
  >
40
41
  <Image
41
42
  src={LogoImage}
42
43
  alt={intl.formatMessage(messages.plonesite)}
43
44
  title={intl.formatMessage(messages.plonesite)}
45
+ width="158.2"
46
+ height="40.7"
44
47
  />
45
48
  </UniversalLink>
46
49
  );
@@ -4,7 +4,7 @@ import { useDispatch } from 'react-redux';
4
4
  import { useCookies } from 'react-cookie';
5
5
  import config from '@plone/volto/registry';
6
6
  import { changeLanguage } from '@plone/volto/actions';
7
- import { normalizeLanguageName } from '@plone/volto/helpers';
7
+ import { toGettextLang } from '@plone/volto/helpers';
8
8
 
9
9
  const MultilingualRedirector = (props) => {
10
10
  const { settings } = config;
@@ -23,7 +23,7 @@ const MultilingualRedirector = (props) => {
23
23
  // const detectedLang = (navigator.language || navigator.userLanguage).substring(0, 2);
24
24
  let mounted = true;
25
25
  if (settings.isMultilingual && pathname === '/') {
26
- const langFileName = normalizeLanguageName(redirectToLanguage);
26
+ const langFileName = toGettextLang(redirectToLanguage);
27
27
  import('@root/../locales/' + langFileName + '.json').then((locale) => {
28
28
  if (mounted) {
29
29
  dispatch(changeLanguage(redirectToLanguage, locale.default));
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { NavLink } from 'react-router-dom';
3
- import { isInternalURL } from '@plone/volto/helpers';
3
+ import { isInternalURL, toBackendLang } from '@plone/volto/helpers';
4
4
  import config from '@plone/volto/registry';
5
5
 
6
6
  const NavItem = ({ item, lang }) => {
@@ -15,7 +15,9 @@ const NavItem = ({ item, lang }) => {
15
15
  className="item"
16
16
  activeClassName="active"
17
17
  exact={
18
- settings.isMultilingual ? item.url === `/${lang}` : item.url === ''
18
+ settings.isMultilingual
19
+ ? item.url === `/${toBackendLang(lang)}`
20
+ : item.url === ''
19
21
  }
20
22
  >
21
23
  {item.title}
@@ -1,53 +1,67 @@
1
- /**
2
- * Home container.
3
- * @module components/theme/NotFound/NotFound
4
- */
5
-
6
- import React from 'react';
1
+ import { useEffect } from 'react';
2
+ import { BodyClass, toBackendLang } from '@plone/volto/helpers';
7
3
  import { FormattedMessage } from 'react-intl';
8
4
  import { Link } from 'react-router-dom';
9
5
  import { Container } from 'semantic-ui-react';
10
6
  import { withServerErrorCode } from '@plone/volto/helpers/Utils/Utils';
7
+ import { useDispatch, useSelector } from 'react-redux';
8
+ import { getNavigation } from '@plone/volto/actions';
9
+ import config from '@plone/volto/registry';
11
10
 
12
11
  /**
13
12
  * Not found function.
14
13
  * @function NotFound
15
14
  * @returns {string} Markup of the not found page.
16
15
  */
17
- const NotFound = () => (
18
- <Container className="view-wrapper">
19
- <h1>
20
- <FormattedMessage
21
- id="This page does not seem to exist…"
22
- defaultMessage="This page does not seem to exist…"
23
- />
24
- </h1>
25
- <p className="description">
26
- <FormattedMessage
27
- id="We apologize for the inconvenience, but the page you were trying to access is not at this address. You can use the links below to help you find what you are looking for."
28
- defaultMessage="We apologize for the inconvenience, but the page you were trying to access is not at this address. You can use the links below to help you find what you are looking for."
29
- />
30
- </p>
31
- <p>
32
- <FormattedMessage
33
- id="If you are certain you have the correct web address but are encountering an error, please contact the {site_admin}."
34
- defaultMessage="If you are certain you have the correct web address but are encountering an error, please contact the {site_admin}."
35
- values={{
36
- site_admin: (
37
- <Link to="/contact-form">
38
- <FormattedMessage
39
- id="Site Administration"
40
- defaultMessage="Site Administration"
41
- />
42
- </Link>
43
- ),
44
- }}
45
- />
46
- </p>
47
- <p>
48
- <FormattedMessage id="Thank you." defaultMessage="Thank you." />
49
- </p>
50
- </Container>
51
- );
16
+ const NotFound = () => {
17
+ const dispatch = useDispatch();
18
+ const lang = useSelector((state) => state.intl.locale);
19
+
20
+ useEffect(() => {
21
+ dispatch(
22
+ getNavigation(
23
+ config.settings.isMultilingual ? `/${toBackendLang(lang)}` : '/',
24
+ config.settings.navDepth,
25
+ ),
26
+ );
27
+ }, [dispatch, lang]);
28
+
29
+ return (
30
+ <Container className="view-wrapper">
31
+ <BodyClass className="page-not-found" />
32
+ <h1>
33
+ <FormattedMessage
34
+ id="This page does not seem to exist…"
35
+ defaultMessage="This page does not seem to exist…"
36
+ />
37
+ </h1>
38
+ <p className="description">
39
+ <FormattedMessage
40
+ id="We apologize for the inconvenience, but the page you were trying to access is not at this address. You can use the links below to help you find what you are looking for."
41
+ defaultMessage="We apologize for the inconvenience, but the page you were trying to access is not at this address. You can use the links below to help you find what you are looking for."
42
+ />
43
+ </p>
44
+ <p>
45
+ <FormattedMessage
46
+ id="If you are certain you have the correct web address but are encountering an error, please contact the {site_admin}."
47
+ defaultMessage="If you are certain you have the correct web address but are encountering an error, please contact the {site_admin}."
48
+ values={{
49
+ site_admin: (
50
+ <Link to="/contact-form">
51
+ <FormattedMessage
52
+ id="Site Administration"
53
+ defaultMessage="Site Administration"
54
+ />
55
+ </Link>
56
+ ),
57
+ }}
58
+ />
59
+ </p>
60
+ <p>
61
+ <FormattedMessage id="Thank you." defaultMessage="Thank you." />
62
+ </p>
63
+ </Container>
64
+ );
65
+ };
52
66
 
53
67
  export default withServerErrorCode(404)(NotFound);
@@ -31,7 +31,7 @@ const messages = defineMessages({
31
31
  },
32
32
  usernameTitle: {
33
33
  id: 'My username is',
34
- defaultMessage: 'My username is',
34
+ defaultMessage: 'My user name is',
35
35
  },
36
36
  emailTitle: {
37
37
  id: 'My email is',
@@ -50,8 +50,8 @@ const messages = defineMessages({
50
50
  defaultMessage: 'New password',
51
51
  },
52
52
  passwordDescription: {
53
- id: 'Enter your new password. Minimum 5 characters.',
54
- defaultMessage: 'Enter your new password. Minimum 5 characters.',
53
+ id: 'Enter your new password. Minimum 8 characters.',
54
+ defaultMessage: 'Enter your new password. Minimum 8 characters.',
55
55
  },
56
56
  passwordRepeatTitle: {
57
57
  id: 'Confirm password',
@@ -227,6 +227,9 @@ class PasswordReset extends Component {
227
227
  );
228
228
  }
229
229
  if (this.props.token) {
230
+ const errmsg = this.props.error
231
+ ? this.props.error.response.body.error
232
+ : null;
230
233
  return (
231
234
  <div id="page-password-reset">
232
235
  <Helmet
@@ -238,7 +241,7 @@ class PasswordReset extends Component {
238
241
  description={this.props.intl.formatMessage(messages.description)}
239
242
  onSubmit={this.onSubmit}
240
243
  onCancel={this.onCancel}
241
- error={this.state.error || this.props.error}
244
+ error={this.state.error || errmsg}
242
245
  schema={{
243
246
  fieldsets: [
244
247
  {
@@ -32,7 +32,7 @@ const messages = defineMessages({
32
32
  },
33
33
  usernameTitle: {
34
34
  id: 'label_my_username_is',
35
- defaultMessage: 'My username is',
35
+ defaultMessage: 'My user name is',
36
36
  },
37
37
  emailTitle: {
38
38
  id: 'label_my_email_is',