@plone/volto 18.0.0-alpha.2 → 18.0.0-alpha.4

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 (293) hide show
  1. package/.eslintrc +3 -3
  2. package/.prettierignore +8 -0
  3. package/.prettierrc +12 -0
  4. package/{packages/registry/.release-it.json → .release-it.json} +11 -6
  5. package/CHANGELOG.md +44 -4
  6. package/locales/ca/LC_MESSAGES/volto.po +1 -0
  7. package/locales/de/LC_MESSAGES/volto.po +1 -0
  8. package/locales/en/LC_MESSAGES/volto.po +1 -0
  9. package/locales/es/LC_MESSAGES/volto.po +1 -0
  10. package/locales/eu/LC_MESSAGES/volto.po +1 -0
  11. package/locales/fi/LC_MESSAGES/volto.po +1 -0
  12. package/locales/fr/LC_MESSAGES/volto.po +1 -0
  13. package/locales/it/LC_MESSAGES/volto.po +1 -0
  14. package/locales/ja/LC_MESSAGES/volto.po +1 -0
  15. package/locales/nl/LC_MESSAGES/volto.po +1 -0
  16. package/locales/pt/LC_MESSAGES/volto.po +1 -0
  17. package/locales/pt_BR/LC_MESSAGES/volto.po +1 -0
  18. package/locales/ro/LC_MESSAGES/volto.po +1 -0
  19. package/locales/volto.pot +2 -1
  20. package/locales/zh_CN/LC_MESSAGES/volto.po +1 -0
  21. package/package.json +57 -127
  22. package/razzle.config.js +4 -7
  23. package/src/components/manage/Blocks/Video/Body.jsx +52 -22
  24. package/src/components/manage/Blocks/Video/Body.test.jsx +167 -0
  25. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.jsx +2 -2
  26. package/src/components/manage/Form/Form.jsx +5 -2
  27. package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +19 -2
  28. package/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +46 -39
  29. package/src/config/index.js +0 -4
  30. package/src/icons/divide-horizontal.svg +0 -0
  31. package/src/icons/divide-vertical.svg +0 -0
  32. package/src/icons/hero.svg +0 -0
  33. package/src/icons/slider.svg +0 -0
  34. package/src/icons/summary.svg +0 -0
  35. package/src/middleware/api.js +1 -1
  36. package/theme/themes/default/elements/icon.overrides +0 -0
  37. package/theme/themes/default/globals/reset.overrides +0 -0
  38. package/theme/themes/default/globals/site.variables +0 -0
  39. package/theme/themes/default/modules/dropdown.overrides +0 -0
  40. package/theme/themes/default/modules/dropdown.variables +0 -0
  41. package/theme/themes/default/modules/modal.variables +0 -0
  42. package/theme/themes/default/modules/video.overrides +0 -0
  43. package/theme/themes/default/modules/video.variables +0 -0
  44. package/theme/themes/pastanaga/assets/fonts/icons.eot +0 -0
  45. package/theme/themes/pastanaga/assets/fonts/icons.svg +0 -0
  46. package/theme/themes/pastanaga/assets/fonts/icons.ttf +0 -0
  47. package/theme/themes/pastanaga/assets/fonts/icons.woff +0 -0
  48. package/theme/themes/pastanaga/globals/reset.overrides +0 -0
  49. package/theme/themes/pastanaga/globals/site.variables +0 -0
  50. package/theme/themes/pastanaga/modules/dropdown.variables +0 -0
  51. package/theme/themes/pastanaga/modules/modal.variables +0 -0
  52. package/theme/themes/pastanaga/modules/video.overrides +0 -0
  53. package/theme/themes/pastanaga/modules/video.variables +0 -0
  54. package/tsconfig.json +1 -4
  55. package/types/components/manage/Blocks/Video/Body.d.ts +5 -0
  56. package/types/config/RichTextEditor/index.d.ts +5 -8
  57. package/types/helpers/AsyncConnect/index.d.ts +2 -2
  58. package/types/helpers/Url/Url.d.ts +3 -3
  59. package/types/icons/load-icons.d.ts +1 -1
  60. package/webpack-plugins/webpack-less-plugin.js +1 -0
  61. package/CODE_OF_CONDUCT.md +0 -13
  62. package/CONTRIBUTING.md +0 -7
  63. package/README.md +0 -154
  64. package/RELEASING.md +0 -73
  65. package/ROADMAP.md +0 -30
  66. package/SECURITY.md +0 -14
  67. package/logos/Logo.png +0 -0
  68. package/logos/VoltoLogoEra2-dark-mode.png +0 -0
  69. package/logos/VoltoLogoEra2.png +0 -0
  70. package/logos/volto-colorful.png +0 -0
  71. package/logos/volto-colorful.svg +0 -35
  72. package/logos/volto-guide.png +0 -0
  73. package/logos/volto-h-transparent.svg +0 -6
  74. package/logos/volto-transparent.png +0 -0
  75. package/logos/volto-transparent.svg +0 -19
  76. package/logos/volto-transparent2.svg +0 -5
  77. package/logos/volto-yellow.svg +0 -29
  78. package/logos/volto.sketch +0 -0
  79. package/packages/README.md +0 -7
  80. package/packages/registry/.towncrier/towncrier_template.jinja +0 -10
  81. package/packages/registry/CHANGELOG.md +0 -16
  82. package/packages/registry/README.md +0 -207
  83. package/packages/registry/addon-registry.js +0 -603
  84. package/packages/registry/create-addons-loader.js +0 -116
  85. package/packages/registry/create-theme-addons-loader.js +0 -78
  86. package/packages/registry/news/.gitkeep +0 -0
  87. package/packages/registry/package.json +0 -76
  88. package/packages/registry/src/index.ts +0 -174
  89. package/packages/registry/src/registry.test.js +0 -111
  90. package/packages/registry/tsconfig.json +0 -32
  91. package/packages/scripts/CHANGELOG.md +0 -173
  92. package/packages/scripts/README.md +0 -128
  93. package/packages/scripts/addon/consolidate.js +0 -28
  94. package/packages/scripts/addon/generators.js +0 -213
  95. package/packages/scripts/addon/getAddonInfo.js +0 -65
  96. package/packages/scripts/addon/index.js +0 -88
  97. package/packages/scripts/addon/utils.js +0 -44
  98. package/packages/scripts/backportpr.js +0 -75
  99. package/packages/scripts/changelogupdater.cjs +0 -94
  100. package/packages/scripts/corepackagebump.js +0 -20
  101. package/packages/scripts/i18n.cjs +0 -310
  102. package/packages/scripts/package.json +0 -76
  103. package/packages/scripts/templates/towncrier_template.jinja +0 -10
  104. package/packages/types/Blocks/View.ts +0 -11
  105. package/packages/types/actions.ts +0 -15
  106. package/packages/types/breadcrumbs.ts +0 -10
  107. package/packages/types/config/Blocks.ts +0 -153
  108. package/packages/types/config/Content.ts +0 -62
  109. package/packages/types/config/Settings.ts +0 -86
  110. package/packages/types/config/Views.ts +0 -15
  111. package/packages/types/config/Widgets.ts +0 -7
  112. package/packages/types/config/index.ts +0 -21
  113. package/packages/types/content/common.ts +0 -60
  114. package/packages/types/content/get.ts +0 -66
  115. package/packages/types/index.ts +0 -0
  116. package/packages/types/navigation.ts +0 -12
  117. package/packages/types/package.json +0 -64
  118. package/packages/types/types.ts +0 -61
  119. package/packages/volto-slate/.i18n.babel.config.js +0 -1
  120. package/packages/volto-slate/README.md +0 -4
  121. package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +0 -90
  122. package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +0 -6
  123. package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +0 -6
  124. package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +0 -6
  125. package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +0 -10
  126. package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +0 -10
  127. package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +0 -30
  128. package/packages/volto-slate/build/messages/src/elementEditor/messages.json +0 -10
  129. package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +0 -6
  130. package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +0 -6
  131. package/packages/volto-slate/locales/de/LC_MESSAGES/volto.po +0 -148
  132. package/packages/volto-slate/locales/en/LC_MESSAGES/volto.po +0 -148
  133. package/packages/volto-slate/locales/volto.pot +0 -182
  134. package/packages/volto-slate/package.json +0 -43
  135. package/packages/volto-slate/src/actions/content.js +0 -30
  136. package/packages/volto-slate/src/actions/index.js +0 -3
  137. package/packages/volto-slate/src/actions/plugins.js +0 -9
  138. package/packages/volto-slate/src/actions/selection.js +0 -22
  139. package/packages/volto-slate/src/blocks/Table/Cell.jsx +0 -87
  140. package/packages/volto-slate/src/blocks/Table/Cell.test.js +0 -54
  141. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.jsx +0 -694
  142. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.test.js +0 -40
  143. package/packages/volto-slate/src/blocks/Table/TableBlockView.jsx +0 -150
  144. package/packages/volto-slate/src/blocks/Table/TableBlockView.test.js +0 -49
  145. package/packages/volto-slate/src/blocks/Table/deconstruct.js +0 -113
  146. package/packages/volto-slate/src/blocks/Table/extensions/normalizeTable.js +0 -5
  147. package/packages/volto-slate/src/blocks/Table/index.js +0 -60
  148. package/packages/volto-slate/src/blocks/Table/schema.js +0 -122
  149. package/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx +0 -304
  150. package/packages/volto-slate/src/blocks/Text/DetachedTextBlockEditor.jsx +0 -77
  151. package/packages/volto-slate/src/blocks/Text/MarkdownIntroduction.jsx +0 -59
  152. package/packages/volto-slate/src/blocks/Text/PluginSidebar.jsx +0 -18
  153. package/packages/volto-slate/src/blocks/Text/ShortcutListing.jsx +0 -28
  154. package/packages/volto-slate/src/blocks/Text/SlashMenu.jsx +0 -203
  155. package/packages/volto-slate/src/blocks/Text/TextBlockEdit.jsx +0 -38
  156. package/packages/volto-slate/src/blocks/Text/TextBlockEdit.test.js +0 -107
  157. package/packages/volto-slate/src/blocks/Text/TextBlockSchema.js +0 -54
  158. package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +0 -31
  159. package/packages/volto-slate/src/blocks/Text/css/editor.css +0 -18
  160. package/packages/volto-slate/src/blocks/Text/extensions/Readme.md +0 -49
  161. package/packages/volto-slate/src/blocks/Text/extensions/breakList.js +0 -100
  162. package/packages/volto-slate/src/blocks/Text/extensions/index.js +0 -6
  163. package/packages/volto-slate/src/blocks/Text/extensions/insertBreak.js +0 -57
  164. package/packages/volto-slate/src/blocks/Text/extensions/isSelected.js +0 -7
  165. package/packages/volto-slate/src/blocks/Text/extensions/normalizeExternalData.js +0 -7
  166. package/packages/volto-slate/src/blocks/Text/extensions/withDeserializers.js +0 -87
  167. package/packages/volto-slate/src/blocks/Text/extensions/withLists.js +0 -5
  168. package/packages/volto-slate/src/blocks/Text/index.js +0 -171
  169. package/packages/volto-slate/src/blocks/Text/keyboard/backspaceInList.js +0 -58
  170. package/packages/volto-slate/src/blocks/Text/keyboard/breakBlocks.js +0 -3
  171. package/packages/volto-slate/src/blocks/Text/keyboard/cancelEsc.js +0 -7
  172. package/packages/volto-slate/src/blocks/Text/keyboard/indentListItems.js +0 -240
  173. package/packages/volto-slate/src/blocks/Text/keyboard/index.js +0 -52
  174. package/packages/volto-slate/src/blocks/Text/keyboard/joinBlocks.js +0 -180
  175. package/packages/volto-slate/src/blocks/Text/keyboard/moveListItems.js +0 -124
  176. package/packages/volto-slate/src/blocks/Text/keyboard/slashMenu.js +0 -19
  177. package/packages/volto-slate/src/blocks/Text/keyboard/softBreak.js +0 -7
  178. package/packages/volto-slate/src/blocks/Text/keyboard/traverseBlocks.js +0 -81
  179. package/packages/volto-slate/src/blocks/Text/keyboard/unwrapEmptyString.js +0 -26
  180. package/packages/volto-slate/src/blocks/Text/schema.js +0 -39
  181. package/packages/volto-slate/src/constants.js +0 -123
  182. package/packages/volto-slate/src/editor/EditorContext.jsx +0 -5
  183. package/packages/volto-slate/src/editor/EditorReference.jsx +0 -22
  184. package/packages/volto-slate/src/editor/SlateEditor.jsx +0 -375
  185. package/packages/volto-slate/src/editor/config.jsx +0 -344
  186. package/packages/volto-slate/src/editor/decorate.js +0 -68
  187. package/packages/volto-slate/src/editor/deserialize.js +0 -185
  188. package/packages/volto-slate/src/editor/extensions/index.js +0 -6
  189. package/packages/volto-slate/src/editor/extensions/insertBreak.js +0 -15
  190. package/packages/volto-slate/src/editor/extensions/insertData.js +0 -159
  191. package/packages/volto-slate/src/editor/extensions/isInline.js +0 -14
  192. package/packages/volto-slate/src/editor/extensions/normalizeExternalData.js +0 -8
  193. package/packages/volto-slate/src/editor/extensions/normalizeNode.js +0 -48
  194. package/packages/volto-slate/src/editor/extensions/withDeserializers.js +0 -15
  195. package/packages/volto-slate/src/editor/extensions/withTestingFeatures.jsx +0 -84
  196. package/packages/volto-slate/src/editor/index.js +0 -14
  197. package/packages/volto-slate/src/editor/less/editor.less +0 -173
  198. package/packages/volto-slate/src/editor/less/globals.less +0 -18
  199. package/packages/volto-slate/src/editor/less/slate.less +0 -28
  200. package/packages/volto-slate/src/editor/plugins/AdvancedLink/deserialize.js +0 -90
  201. package/packages/volto-slate/src/editor/plugins/AdvancedLink/extensions.js +0 -32
  202. package/packages/volto-slate/src/editor/plugins/AdvancedLink/index.js +0 -50
  203. package/packages/volto-slate/src/editor/plugins/AdvancedLink/render.jsx +0 -37
  204. package/packages/volto-slate/src/editor/plugins/AdvancedLink/schema.js +0 -114
  205. package/packages/volto-slate/src/editor/plugins/AdvancedLink/styles.less +0 -8
  206. package/packages/volto-slate/src/editor/plugins/Blockquote/index.js +0 -30
  207. package/packages/volto-slate/src/editor/plugins/Callout/index.js +0 -34
  208. package/packages/volto-slate/src/editor/plugins/Image/deconstruct.js +0 -30
  209. package/packages/volto-slate/src/editor/plugins/Image/extensions.js +0 -51
  210. package/packages/volto-slate/src/editor/plugins/Image/index.js +0 -11
  211. package/packages/volto-slate/src/editor/plugins/Image/render.jsx +0 -22
  212. package/packages/volto-slate/src/editor/plugins/Link/extensions.js +0 -58
  213. package/packages/volto-slate/src/editor/plugins/Link/index.js +0 -164
  214. package/packages/volto-slate/src/editor/plugins/Link/render.jsx +0 -54
  215. package/packages/volto-slate/src/editor/plugins/Markdown/constants.js +0 -81
  216. package/packages/volto-slate/src/editor/plugins/Markdown/extensions.js +0 -334
  217. package/packages/volto-slate/src/editor/plugins/Markdown/index.js +0 -28
  218. package/packages/volto-slate/src/editor/plugins/Markdown/utils.js +0 -198
  219. package/packages/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx +0 -153
  220. package/packages/volto-slate/src/editor/plugins/StyleMenu/index.js +0 -19
  221. package/packages/volto-slate/src/editor/plugins/StyleMenu/style.less +0 -29
  222. package/packages/volto-slate/src/editor/plugins/StyleMenu/utils.js +0 -168
  223. package/packages/volto-slate/src/editor/plugins/Table/TableButton.jsx +0 -142
  224. package/packages/volto-slate/src/editor/plugins/Table/TableCell.jsx +0 -44
  225. package/packages/volto-slate/src/editor/plugins/Table/TableContainer.jsx +0 -37
  226. package/packages/volto-slate/src/editor/plugins/Table/TableSizePicker.jsx +0 -83
  227. package/packages/volto-slate/src/editor/plugins/Table/extensions.js +0 -87
  228. package/packages/volto-slate/src/editor/plugins/Table/index.js +0 -390
  229. package/packages/volto-slate/src/editor/plugins/Table/less/public.less +0 -29
  230. package/packages/volto-slate/src/editor/plugins/Table/less/table.less +0 -28
  231. package/packages/volto-slate/src/editor/plugins/Table/render.jsx +0 -30
  232. package/packages/volto-slate/src/editor/plugins/index.js +0 -19
  233. package/packages/volto-slate/src/editor/render.jsx +0 -224
  234. package/packages/volto-slate/src/editor/ui/BasicToolbar.jsx +0 -11
  235. package/packages/volto-slate/src/editor/ui/BlockButton.jsx +0 -31
  236. package/packages/volto-slate/src/editor/ui/ClearFormattingButton.jsx +0 -21
  237. package/packages/volto-slate/src/editor/ui/ExpandedToolbar.jsx +0 -18
  238. package/packages/volto-slate/src/editor/ui/Expando.jsx +0 -5
  239. package/packages/volto-slate/src/editor/ui/InlineToolbar.jsx +0 -73
  240. package/packages/volto-slate/src/editor/ui/MarkButton.jsx +0 -23
  241. package/packages/volto-slate/src/editor/ui/MarkElementButton.jsx +0 -30
  242. package/packages/volto-slate/src/editor/ui/Menu.jsx +0 -13
  243. package/packages/volto-slate/src/editor/ui/PositionedToolbar.jsx +0 -32
  244. package/packages/volto-slate/src/editor/ui/Separator.jsx +0 -7
  245. package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +0 -13
  246. package/packages/volto-slate/src/editor/ui/SlateToolbar.jsx +0 -96
  247. package/packages/volto-slate/src/editor/ui/Toolbar.jsx +0 -103
  248. package/packages/volto-slate/src/editor/ui/ToolbarButton.jsx +0 -33
  249. package/packages/volto-slate/src/editor/ui/ToolbarButton.test.js +0 -25
  250. package/packages/volto-slate/src/editor/ui/index.js +0 -15
  251. package/packages/volto-slate/src/editor/utils.js +0 -248
  252. package/packages/volto-slate/src/elementEditor/ContextButtons.jsx +0 -56
  253. package/packages/volto-slate/src/elementEditor/PluginEditor.jsx +0 -124
  254. package/packages/volto-slate/src/elementEditor/Readme.md +0 -6
  255. package/packages/volto-slate/src/elementEditor/SchemaProvider.jsx +0 -3
  256. package/packages/volto-slate/src/elementEditor/SidebarEditor.jsx +0 -46
  257. package/packages/volto-slate/src/elementEditor/ToolbarButton.jsx +0 -44
  258. package/packages/volto-slate/src/elementEditor/index.js +0 -5
  259. package/packages/volto-slate/src/elementEditor/makeInlineElementPlugin.js +0 -100
  260. package/packages/volto-slate/src/elementEditor/messages.js +0 -14
  261. package/packages/volto-slate/src/elementEditor/utils.js +0 -226
  262. package/packages/volto-slate/src/hooks/index.js +0 -3
  263. package/packages/volto-slate/src/hooks/useEditorContext.js +0 -6
  264. package/packages/volto-slate/src/hooks/useIsomorphicLayoutEffect.js +0 -7
  265. package/packages/volto-slate/src/hooks/useSelectionPosition.js +0 -25
  266. package/packages/volto-slate/src/i18n.js +0 -180
  267. package/packages/volto-slate/src/icons/hashlink.svg +0 -57
  268. package/packages/volto-slate/src/index.js +0 -61
  269. package/packages/volto-slate/src/reducers/content.js +0 -74
  270. package/packages/volto-slate/src/reducers/index.js +0 -3
  271. package/packages/volto-slate/src/reducers/plugins.js +0 -17
  272. package/packages/volto-slate/src/reducers/selection.js +0 -16
  273. package/packages/volto-slate/src/utils/blocks.js +0 -375
  274. package/packages/volto-slate/src/utils/blocks.test.js +0 -138
  275. package/packages/volto-slate/src/utils/editor.js +0 -31
  276. package/packages/volto-slate/src/utils/image.js +0 -25
  277. package/packages/volto-slate/src/utils/index.js +0 -11
  278. package/packages/volto-slate/src/utils/internals.js +0 -46
  279. package/packages/volto-slate/src/utils/lists.js +0 -92
  280. package/packages/volto-slate/src/utils/marks.js +0 -104
  281. package/packages/volto-slate/src/utils/mime-types.js +0 -24
  282. package/packages/volto-slate/src/utils/nodes.js +0 -4
  283. package/packages/volto-slate/src/utils/ops.js +0 -20
  284. package/packages/volto-slate/src/utils/random.js +0 -17
  285. package/packages/volto-slate/src/utils/selection.js +0 -236
  286. package/packages/volto-slate/src/utils/slate-string-utils.js +0 -408
  287. package/packages/volto-slate/src/utils/volto-blocks.js +0 -314
  288. package/packages/volto-slate/src/widgets/ErrorBoundary.jsx +0 -27
  289. package/packages/volto-slate/src/widgets/HtmlSlateWidget.jsx +0 -139
  290. package/packages/volto-slate/src/widgets/ObjectByTypeWidget.jsx +0 -49
  291. package/packages/volto-slate/src/widgets/RichTextWidget.jsx +0 -72
  292. package/packages/volto-slate/src/widgets/RichTextWidgetView.jsx +0 -37
  293. package/packages/volto-slate/src/widgets/style.css +0 -21
@@ -5,39 +5,68 @@ import { Embed, Message } from 'semantic-ui-react';
5
5
  import cx from 'classnames';
6
6
  import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers';
7
7
 
8
- const Body = ({ data, isEditMode }) => {
9
- let placeholder = data.preview_image
10
- ? isInternalURL(data.preview_image)
11
- ? `${flattenToAppURL(data.preview_image)}/@@images/image`
12
- : data.preview_image
13
- : null;
14
-
8
+ //Extracting videoID, listID and thumbnailURL from the video URL
9
+ const getVideoIDAndPlaceholder = (url) => {
15
10
  let videoID = null;
16
11
  let listID = null;
12
+ let thumbnailURL = null;
17
13
 
18
- if (data.url) {
19
- if (data.url.match('youtu')) {
20
- if (data.url.match('list')) {
21
- const matches = data.url.match(/^.*\?list=(.*)|^.*&list=(.*)$/);
14
+ if (url) {
15
+ if (url.match('youtu')) {
16
+ if (url.match('list')) {
17
+ const matches = url.match(/^.*\?list=(.*)|^.*&list=(.*)$/);
22
18
  listID = matches[1] || matches[2];
23
- } else {
24
- videoID = data.url.match(/.be\//)
25
- ? data.url.match(/^.*\.be\/(.*)/)[1]
26
- : data.url.match(/^.*\?v=(.*)$/)[1];
19
+
20
+ let thumbnailID = null;
21
+ if (url.match(/\?v=(.*)&list/)) {
22
+ thumbnailID = url.match(/^.*\?v=(.*)&list(.*)/)[1];
23
+ }
24
+ if (url.match(/\?v=(.*)\?list/)) {
25
+ thumbnailID = url.match(/^.*\?v=(.*)\?list(.*)/)[1];
26
+ }
27
+ thumbnailURL =
28
+ 'https://img.youtube.com/vi/' + thumbnailID + '/sddefault.jpg';
29
+ } else if (url.match('live')) {
30
+ videoID = url.match(/^.*\/live\/(.*)/)[1];
31
+ } else if (url.match(/\.be\//)) {
32
+ videoID = url.match(/^.*\.be\/(.*)/)[1];
33
+ } else if (url.match(/\?v=/)) {
34
+ videoID = url.match(/^.*\?v=(.*)$/)[1];
27
35
  }
28
36
 
29
- if (!placeholder) {
37
+ if (videoID) {
38
+ let thumbnailID = videoID;
39
+ if (videoID.match(/\?si=/)) {
40
+ thumbnailID = videoID.match(/(.*)\?si=(.*)/)[1];
41
+ }
30
42
  //load video preview image from youtube
31
- placeholder =
32
- 'https://img.youtube.com/vi/' + videoID + '/sddefault.jpg';
43
+ thumbnailURL =
44
+ 'https://img.youtube.com/vi/' + thumbnailID + '/sddefault.jpg';
33
45
  }
34
- } else if (data.url.match('vimeo')) {
35
- videoID = data.url.match(/^.*\.com\/(.*)/)[1];
36
- if (!placeholder) {
37
- placeholder = 'https://vumbnail.com/' + videoID + '.jpg';
46
+ } else if (url.match('vimeo')) {
47
+ videoID = url.match(/^.*\.com\/(.*)/)[1];
48
+ if (videoID) {
49
+ let thumbnailID = videoID;
50
+ if (videoID.match(/\?si=/)) {
51
+ thumbnailID = videoID.match(/(.*)\?si=(.*)/)[1];
52
+ }
53
+ thumbnailURL = 'https://vumbnail.com/' + thumbnailID + '.jpg';
38
54
  }
39
55
  }
40
56
  }
57
+ return { videoID, listID, thumbnailURL };
58
+ };
59
+
60
+ const Body = ({ data, isEditMode }) => {
61
+ let placeholder = data.preview_image
62
+ ? isInternalURL(data.preview_image)
63
+ ? `${flattenToAppURL(data.preview_image)}/@@images/image`
64
+ : data.preview_image
65
+ : null;
66
+
67
+ const { videoID, listID, thumbnailURL } = getVideoIDAndPlaceholder(data.url);
68
+
69
+ placeholder = !placeholder ? thumbnailURL : placeholder;
41
70
 
42
71
  const ref = React.createRef();
43
72
  const onKeyDown = (e) => {
@@ -130,3 +159,4 @@ Body.propTypes = {
130
159
  };
131
160
 
132
161
  export default Body;
162
+ export { getVideoIDAndPlaceholder };
@@ -0,0 +1,167 @@
1
+ import React from 'react';
2
+ import renderer from 'react-test-renderer';
3
+ import configureStore from 'redux-mock-store';
4
+ import { Provider } from 'react-intl-redux';
5
+ import Body from './Body';
6
+ import { getVideoIDAndPlaceholder } from './Body';
7
+ import config from '@plone/volto/registry';
8
+
9
+ config.blocks.blocksConfig = {
10
+ video: {
11
+ id: 'video',
12
+ title: 'Video',
13
+ group: 'media',
14
+ extensions: {},
15
+ variations: [],
16
+ restricted: false,
17
+ mostUsed: true,
18
+ sidebarTab: 1,
19
+ security: {
20
+ addPermission: [],
21
+ view: [],
22
+ },
23
+ },
24
+ };
25
+
26
+ const mockStore = configureStore();
27
+
28
+ test('renders a youtube video component with "list" in its url', () => {
29
+ const url =
30
+ 'https://www.youtube.com/watch?v=KwRSRRyuk-Q&list=PLGN9BI-OAQkQmEqf6O8jeyoFY1b2hD1uL&index=1';
31
+ const videoDetails = getVideoIDAndPlaceholder(url);
32
+ expect(videoDetails).toEqual({
33
+ videoID: null,
34
+ listID: 'PLGN9BI-OAQkQmEqf6O8jeyoFY1b2hD1uL&index=1',
35
+ thumbnailURL: 'https://img.youtube.com/vi/KwRSRRyuk-Q/sddefault.jpg',
36
+ });
37
+ });
38
+
39
+ test('extracts video details from a youtube video with "/live/" in its url', () => {
40
+ const url = 'https://www.youtube.com/live/ISdHvS6Ck3k?si=COeVakmC1lI6jQy3';
41
+ const videoDetails = getVideoIDAndPlaceholder(url);
42
+ expect(videoDetails).toEqual({
43
+ videoID: 'ISdHvS6Ck3k?si=COeVakmC1lI6jQy3',
44
+ listID: null,
45
+ thumbnailURL: 'https://img.youtube.com/vi/ISdHvS6Ck3k/sddefault.jpg',
46
+ });
47
+ });
48
+
49
+ test('extracts video details from a youtube video with ".be/" in its url', () => {
50
+ const url = 'https://youtu.be/P9j-xYdWT28?si=zZ2putStJbPBLCdt';
51
+ const videoDetails = getVideoIDAndPlaceholder(url);
52
+ expect(videoDetails).toEqual({
53
+ videoID: 'P9j-xYdWT28?si=zZ2putStJbPBLCdt',
54
+ listID: null,
55
+ thumbnailURL: 'https://img.youtube.com/vi/P9j-xYdWT28/sddefault.jpg',
56
+ });
57
+ });
58
+
59
+ test('extracts video details from a youtube video with "?v=" in its url', () => {
60
+ const url = 'https://www.youtube.com/watch?v=KUd6e105u_I';
61
+ const videoDetails = getVideoIDAndPlaceholder(url);
62
+ expect(videoDetails).toEqual({
63
+ videoID: 'KUd6e105u_I',
64
+ listID: null,
65
+ thumbnailURL: 'https://img.youtube.com/vi/KUd6e105u_I/sddefault.jpg',
66
+ });
67
+ });
68
+
69
+ test('extracts video details from a vimeo video url', () => {
70
+ const url = 'https://vimeo.com/639449679';
71
+ const videoDetails = getVideoIDAndPlaceholder(url);
72
+ expect(videoDetails).toEqual({
73
+ videoID: '639449679',
74
+ listID: null,
75
+ thumbnailURL: 'https://vumbnail.com/639449679.jpg',
76
+ });
77
+ });
78
+
79
+ test('renders a youtube video body component', () => {
80
+ const store = mockStore({
81
+ intl: {
82
+ locale: 'en',
83
+ messages: {},
84
+ },
85
+ });
86
+
87
+ const component = renderer.create(
88
+ <Provider store={store}>
89
+ <Body
90
+ data={{
91
+ '@type': 'video',
92
+ url: 'https://www.youtube.com/watch?v=KwRSRRyuk-Q&list=PLGN9BI-OAQkQmEqf6O8jeyoFY1b2hD1uL&index=1',
93
+ }}
94
+ />
95
+ </Provider>,
96
+ );
97
+ const json = component.toJSON();
98
+ expect(json).toMatchSnapshot();
99
+ });
100
+
101
+ test('renders a youtube video body component in edit mode', () => {
102
+ const store = mockStore({
103
+ intl: {
104
+ locale: 'en',
105
+ messages: {},
106
+ },
107
+ });
108
+
109
+ const component = renderer.create(
110
+ <Provider store={store}>
111
+ <Body
112
+ data={{
113
+ '@type': 'video',
114
+ url: 'https://www.youtube.com/watch?v=KwRSRRyuk-Q&list=PLGN9BI-OAQkQmEqf6O8jeyoFY1b2hD1uL&index=1',
115
+ }}
116
+ isEditMode={true}
117
+ />
118
+ </Provider>,
119
+ );
120
+ const json = component.toJSON();
121
+ expect(json).toMatchSnapshot();
122
+ });
123
+
124
+ test('renders invalid video body component with invalid URL', () => {
125
+ const store = mockStore({
126
+ intl: {
127
+ locale: 'en',
128
+ messages: {},
129
+ },
130
+ });
131
+
132
+ const component = renderer.create(
133
+ <Provider store={store}>
134
+ <Body
135
+ data={{
136
+ '@type': 'video',
137
+ url: 'https://www.google.com',
138
+ }}
139
+ />
140
+ </Provider>,
141
+ );
142
+ const json = component.toJSON();
143
+ expect(json).toMatchSnapshot();
144
+ });
145
+
146
+ test('renders a error message for invalid video URL in edit mode', () => {
147
+ const store = mockStore({
148
+ intl: {
149
+ locale: 'en',
150
+ messages: {},
151
+ },
152
+ });
153
+
154
+ const component = renderer.create(
155
+ <Provider store={store}>
156
+ <Body
157
+ data={{
158
+ '@type': 'video',
159
+ url: 'https://www.google.com',
160
+ }}
161
+ isEditMode={true}
162
+ />
163
+ </Provider>,
164
+ );
165
+ const json = component.toJSON();
166
+ expect(json).toMatchSnapshot();
167
+ });
@@ -3,7 +3,7 @@
3
3
  * TODO Enrich with features of user control panel. Then replace user control panel.
4
4
  */
5
5
  import React, { useEffect } from 'react';
6
- import { find, toNumber } from 'lodash';
6
+ import { find } from 'lodash';
7
7
  import { Portal } from 'react-portal';
8
8
  import { useHistory } from 'react-router';
9
9
  import { Link, useLocation } from 'react-router-dom';
@@ -38,7 +38,7 @@ const UserGroupMembershipPanel = () => {
38
38
  (state) => state.controlpanels.systeminformation,
39
39
  );
40
40
  const can_use_group_membership_panel = systeminformation
41
- ? toNumber(systeminformation?.plone_restapi_version.slice(0, 4)) >= 8.24
41
+ ? parseFloat(systeminformation?.plone_restapi_version.slice(0, 4)) >= 8.24
42
42
  : false;
43
43
  const actions = useSelector((state) => state.actions?.actions ?? {});
44
44
  const ploneSetupAction = find(actions.user, {
@@ -148,7 +148,10 @@ class Form extends Component {
148
148
  ...formData,
149
149
  };
150
150
  }
151
- // defaults for block editor; should be moved to schema on server side
151
+
152
+ // We initialize the formData snapshot in here, before the initial data checks
153
+ const initialFormData = cloneDeep(formData);
154
+
152
155
  // Adding fallback in case the fields are empty, so we are sure that the edit form
153
156
  // shows at least the default blocks
154
157
  if (
@@ -200,7 +203,7 @@ class Form extends Component {
200
203
 
201
204
  this.state = {
202
205
  formData,
203
- initialFormData: cloneDeep(formData),
206
+ initialFormData,
204
207
  errors: {},
205
208
  selected: selectedBlock,
206
209
  multiSelected: [],
@@ -1,6 +1,6 @@
1
1
  import { useEffect } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Link } from 'react-router-dom';
3
+ import { Link, useLocation } from 'react-router-dom';
4
4
  import { Breadcrumb, Container, Segment } from 'semantic-ui-react';
5
5
  import { defineMessages, useIntl } from 'react-intl';
6
6
  import { useDispatch, useSelector, shallowEqual } from 'react-redux';
@@ -19,13 +19,30 @@ const messages = defineMessages({
19
19
  id: 'Breadcrumbs',
20
20
  defaultMessage: 'Breadcrumbs',
21
21
  },
22
+ controlpanel: {
23
+ id: 'Site Setup',
24
+ defaultMessage: 'Site Setup',
25
+ },
22
26
  });
23
27
 
24
28
  const BreadcrumbsComponent = ({ pathname }) => {
25
29
  const intl = useIntl();
26
30
  const dispatch = useDispatch();
31
+ const { pathname: realPath } = useLocation();
32
+ const controlpanelItems = [
33
+ {
34
+ url: '/controlpanel',
35
+ title: intl.formatMessage(messages.controlpanel),
36
+ },
37
+ ];
27
38
 
28
- const items = useSelector((state) => state.breadcrumbs.items, shallowEqual);
39
+ const items = useSelector(
40
+ (state) =>
41
+ realPath.startsWith('/controlpanel')
42
+ ? controlpanelItems
43
+ : state.breadcrumbs.items,
44
+ shallowEqual,
45
+ );
29
46
  const root = useSelector((state) => state.breadcrumbs.root);
30
47
 
31
48
  useEffect(() => {
@@ -1,5 +1,13 @@
1
- import { toPublicURL, Helmet } from '@plone/volto/helpers';
1
+ import React, { useEffect } from 'react';
2
+ import {
3
+ toPublicURL,
4
+ Helmet,
5
+ hasApiExpander,
6
+ getBaseUrl,
7
+ } from '@plone/volto/helpers';
8
+ import { getNavroot } from '@plone/volto/actions';
2
9
  import config from '@plone/volto/registry';
10
+ import { useDispatch, useSelector } from 'react-redux';
3
11
 
4
12
  const ContentMetadataTags = (props) => {
5
13
  const {
@@ -13,23 +21,21 @@ const ContentMetadataTags = (props) => {
13
21
  description,
14
22
  } = props.content;
15
23
 
24
+ const dispatch = useDispatch();
25
+ const pathname = useSelector((state) => state.router.location.pathname);
26
+ const navroot = useSelector((state) => state.navroot?.data?.navroot);
27
+ const site = useSelector((state) => state.site?.data);
28
+
29
+ useEffect(() => {
30
+ if (pathname && !hasApiExpander('navroot', getBaseUrl(pathname))) {
31
+ dispatch(getNavroot(getBaseUrl(pathname)));
32
+ }
33
+ }, [dispatch, pathname]);
34
+
16
35
  const getContentImageInfo = () => {
17
36
  const { contentMetadataTagsImageField } = config.settings;
18
- const image_field = props.content[contentMetadataTagsImageField];
19
- const preview_image = props.content.preview_image;
20
- const preview_image_link = props.content.preview_image_link;
37
+ const image = props.content[contentMetadataTagsImageField];
21
38
  const { opengraph_image } = props.content;
22
- let image = undefined;
23
-
24
- if (opengraph_image !== undefined && opengraph_image) {
25
- image = opengraph_image;
26
- } else if (preview_image_link !== undefined && preview_image_link) {
27
- image = preview_image_link[contentMetadataTagsImageField];
28
- } else if (preview_image !== undefined && preview_image) {
29
- image = preview_image;
30
- } else if (image_field !== undefined && image_field) {
31
- image = image_field;
32
- }
33
39
 
34
40
  const contentImageInfo = {
35
41
  contentHasImage: false,
@@ -37,7 +43,10 @@ const ContentMetadataTags = (props) => {
37
43
  height: null,
38
44
  width: null,
39
45
  };
40
- contentImageInfo.contentHasImage = image?.scales?.large?.download || false;
46
+ contentImageInfo.contentHasImage =
47
+ opengraph_image?.scales?.large?.download ||
48
+ image?.scales?.large?.download ||
49
+ false;
41
50
 
42
51
  if (contentImageInfo.contentHasImage && opengraph_image?.scales?.large) {
43
52
  contentImageInfo.url = opengraph_image.scales.large.download;
@@ -54,16 +63,35 @@ const ContentMetadataTags = (props) => {
54
63
 
55
64
  const contentImageInfo = getContentImageInfo();
56
65
 
66
+ const getTitle = () => {
67
+ const includeSiteTitle =
68
+ config?.settings?.siteTitleFormat?.includeSiteTitle || false;
69
+ const titleAndSiteTitleSeparator =
70
+ config?.settings?.titleAndSiteTitleSeparator || '-';
71
+ const navRootTitle = navroot?.title;
72
+ const siteRootTitle = site?.['plone.site_title'];
73
+ const titlePart = navRootTitle || siteRootTitle;
74
+
75
+ if (includeSiteTitle && titlePart && titlePart !== title) {
76
+ return seo_title || `${title} ${titleAndSiteTitleSeparator} ${titlePart}`;
77
+ } else {
78
+ return seo_title || title;
79
+ }
80
+ };
81
+
57
82
  return (
58
83
  <>
59
84
  <Helmet>
60
- <title>{(seo_title || title)?.replace(/\u00AD/g, '')}</title>
85
+ <title>{getTitle()?.replace(/\u00AD/g, '')}</title>
86
+ <link
87
+ rel="canonical"
88
+ href={seo_canonical_url || toPublicURL(props.content['@id'])}
89
+ />
61
90
  <meta name="description" content={seo_description || description} />
62
91
  <meta
63
92
  property="og:title"
64
93
  content={opengraph_title || seo_title || title}
65
94
  />
66
- <meta property="og:type" content={'website'} />
67
95
  <meta
68
96
  property="og:url"
69
97
  content={seo_canonical_url || toPublicURL(props.content['@id'])}
@@ -75,12 +103,6 @@ const ContentMetadataTags = (props) => {
75
103
  content={toPublicURL(contentImageInfo.url)}
76
104
  />
77
105
  )}
78
- {contentImageInfo.contentHasImage && (
79
- <meta
80
- property="twitter:image"
81
- content={toPublicURL(contentImageInfo.url)}
82
- />
83
- )}
84
106
  {contentImageInfo.contentHasImage && (
85
107
  <meta property="og:image:width" content={contentImageInfo.width} />
86
108
  )}
@@ -94,21 +116,6 @@ const ContentMetadataTags = (props) => {
94
116
  />
95
117
  )}
96
118
  <meta name="twitter:card" content="summary_large_image" />
97
- <meta
98
- property="twitter:url"
99
- content={seo_canonical_url || toPublicURL(props.content['@id'])}
100
- />
101
- {/* TODO: Improve SEO backend metadata providers by adding the twitter handler */}
102
- {/* <meta property="twitter:site" content={'@my_twitter_handler'} /> */}
103
- <meta
104
- property="twitter:title"
105
- content={opengraph_title || seo_title || title}
106
- />
107
- <meta
108
- property="twitter:description"
109
- content={seo_description || description}
110
- />
111
- <meta property="twitter:domain" content={config.settings.publicURL} />
112
119
  </Helmet>
113
120
  </>
114
121
  );
@@ -1,7 +1,3 @@
1
- /**
2
- * Config.
3
- * @module config
4
- */
5
1
  import { parse as parseUrl } from 'url';
6
2
  import { defaultWidget, widgetMapping } from './Widgets';
7
3
  import {
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -230,7 +230,7 @@ const apiMiddlewareFactory =
230
230
  config.settings.supportedLanguages.includes(lang)
231
231
  ) {
232
232
  const langFileName = toGettextLang(lang);
233
- import('~/../locales/' + langFileName + '.json').then(
233
+ import('@root/../locales/' + langFileName + '.json').then(
234
234
  (locale) => {
235
235
  dispatch(changeLanguage(lang, locale.default));
236
236
  },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/tsconfig.json CHANGED
@@ -17,10 +17,7 @@
17
17
  "jsx": "react-jsx",
18
18
  "paths": {
19
19
  "@plone/volto/*": ["./src/*"],
20
- "@plone/volto-slate/*": ["./packages/volto-slate/src/*"],
21
- "@plone/registry/*": ["./packages/registry/src/*"],
22
- "@plone/registry": ["./packages/registry/src"],
23
- "@plone/types/*": ["./packages/types/*"],
20
+ "@plone/volto-slate/*": ["../volto-slate/src/*"],
24
21
  "@root/*": ["./src/*"]
25
22
  }
26
23
  },
@@ -8,3 +8,8 @@ declare namespace Body {
8
8
  let data: any;
9
9
  }
10
10
  }
11
+ export function getVideoIDAndPlaceholder(url: any): {
12
+ videoID: any;
13
+ listID: any;
14
+ thumbnailURL: string;
15
+ };
@@ -1,16 +1,13 @@
1
1
  export function richtextEditorSettings(props: any): {
2
2
  extendedBlockRenderMap: any;
3
- blockStyleFn: (contentBlock: any) => string;
4
- listBlockTypes: string[];
5
- richTextEditorPlugins: any[];
6
- richTextEditorInlineToolbarButtons: any[];
7
- FromHTMLCustomBlockFn: typeof FromHTMLCustomBlockFn;
3
+ blockStyleFn: any;
4
+ listBlockTypes: any;
5
+ richTextEditorPlugins: any;
6
+ richTextEditorInlineToolbarButtons: any;
7
+ FromHTMLCustomBlockFn: any;
8
8
  customStyleMap: any;
9
9
  };
10
10
  export namespace richtextViewSettings {
11
11
  export { ToHTMLRenderers };
12
12
  export { ToHTMLOptions };
13
13
  }
14
- import FromHTMLCustomBlockFn from './FromHTML';
15
- import ToHTMLRenderers from './ToHTML';
16
- import { options as ToHTMLOptions } from './ToHTML';
@@ -14,6 +14,6 @@
14
14
  * with the "object promises" and that's our "object promises" (which it calls
15
15
  * internally "asyncItems").
16
16
  */
17
- export function asyncConnect(asyncItems: any, mapStateToProps: any, mapDispatchToProps: any, mergeProps: any, options: any): (Component: any) => import("react-redux").ConnectedComponent<any, any>;
18
- export const ReduxAsyncConnect: import("react-redux").ConnectedComponent<any, any>;
17
+ export function asyncConnect(asyncItems: any, mapStateToProps: any, mapDispatchToProps: any, mergeProps: any, options: any): (Component: any) => any;
18
+ export const ReduxAsyncConnect: any;
19
19
  export { loadOnServer, loadAsyncConnect } from "./ssr";
@@ -118,21 +118,21 @@ export function flattenScales(path: string, image: object): object;
118
118
  * @param {string} url Url to be parsed.
119
119
  * @return {string} Base url of content object.
120
120
  */
121
- export const getBaseUrl: ((url: any) => any) & import("lodash").MemoizedFunction;
121
+ export const getBaseUrl: any;
122
122
  /**
123
123
  * Get parent url.
124
124
  * @function getParentUrl
125
125
  * @param {string} url Url to be parsed.
126
126
  * @return {string} Parent url of content object.
127
127
  */
128
- export const getParentUrl: ((url: any) => any) & import("lodash").MemoizedFunction;
128
+ export const getParentUrl: any;
129
129
  /**
130
130
  * Returns true if the current view is a cms ui view
131
131
  * @method isCmsUi
132
132
  * @param {string} currentPathname pathname of the current view
133
133
  * @returns {boolean} true if the current view is a cms ui view
134
134
  */
135
- export const isCmsUi: ((currentPathname: any) => any) & import("lodash").MemoizedFunction;
135
+ export const isCmsUi: any;
136
136
  export function getFieldURL(data: object): string | any;
137
137
  export namespace URLUtils {
138
138
  export { normalizeTelephone };
@@ -1,2 +1,2 @@
1
1
  export default icons;
2
- declare const icons: {};
2
+ declare const icons: any;
@@ -140,6 +140,7 @@ module.exports = (userOptions = {}) => ({
140
140
  path.resolve('./theme'),
141
141
  path.resolve('./src'),
142
142
  /node_modules\/@plone\/volto\/theme/,
143
+ /packages\/volto\/theme/,
143
144
  /plone\.volto\/theme/,
144
145
  /node_modules\/semantic-ui-less/,
145
146
  ...Object.values(registry.getResolveAliases()),