@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.
- package/.eslintignore +1 -0
- package/.eslintrc +37 -3
- package/CHANGELOG.md +338 -1
- package/README.md +20 -16
- package/babel.js +1 -3
- package/cypress/docker/prefixed-rules.yml +26 -0
- package/cypress/docker/prefixed.yml +24 -0
- package/cypress/support/commands.js +12 -6
- package/cypress/support/guillotina.js +1 -0
- package/cypress.config.js +1 -0
- package/global-test-setup.js +1 -2
- package/locales/af.json +1 -0
- package/locales/ar.json +1 -0
- package/locales/bg.json +1 -0
- package/locales/bn.json +1 -0
- package/locales/ca/LC_MESSAGES/volto.po +124 -17
- package/locales/ca.json +1 -1
- package/locales/cs.json +1 -0
- package/locales/cy.json +1 -0
- package/locales/da.json +1 -0
- package/locales/de/LC_MESSAGES/volto.po +135 -28
- package/locales/de.json +1 -1
- package/locales/el.json +1 -0
- package/locales/en/LC_MESSAGES/volto.po +125 -18
- package/locales/en.json +1 -1
- package/locales/en_AU.json +1 -0
- package/locales/en_GB.json +1 -0
- package/locales/eo.json +1 -0
- package/locales/es/LC_MESSAGES/volto.po +125 -18
- package/locales/es.json +1 -1
- package/locales/et.json +1 -0
- package/locales/eu/LC_MESSAGES/volto.po +124 -17
- package/locales/eu.json +1 -1
- package/locales/fa.json +1 -0
- package/locales/fi/LC_MESSAGES/volto.po +124 -17
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +125 -18
- package/locales/fr.json +1 -1
- package/locales/fu.json +1 -0
- package/locales/gl.json +1 -0
- package/locales/he.json +1 -0
- package/locales/hi/LC_MESSAGES/volto.po +128 -21
- package/locales/hi.json +1 -1
- package/locales/hr.json +1 -0
- package/locales/hu.json +1 -0
- package/locales/hy.json +1 -0
- package/locales/id.json +1 -0
- package/locales/it/LC_MESSAGES/volto.po +129 -22
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +124 -17
- package/locales/ja.json +1 -1
- package/locales/ka.json +1 -0
- package/locales/kn.json +1 -0
- package/locales/ko.json +1 -0
- package/locales/lt.json +1 -0
- package/locales/lv.json +1 -0
- package/locales/mi.json +1 -0
- package/locales/mk.json +1 -0
- package/locales/my.json +1 -0
- package/locales/nb_NO.json +1 -0
- package/locales/nl/LC_MESSAGES/volto.po +128 -21
- package/locales/nl.json +1 -1
- package/locales/nn.json +1 -0
- package/locales/pl.json +1 -0
- package/locales/pt/LC_MESSAGES/volto.po +124 -17
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +147 -40
- package/locales/pt_BR.json +1 -1
- package/locales/rm.json +1 -0
- package/locales/ro/LC_MESSAGES/volto.po +128 -21
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +128 -21
- package/locales/ru.json +1 -1
- package/locales/sk.json +1 -0
- package/locales/sl.json +1 -0
- package/locales/sm.json +1 -0
- package/locales/sq.json +1 -0
- package/locales/sr.json +1 -0
- package/locales/sr@cyrl.json +1 -0
- package/locales/sr@latn.json +1 -0
- package/locales/sv.json +1 -1
- package/locales/ta.json +1 -0
- package/locales/te.json +1 -0
- package/locales/th.json +1 -0
- package/locales/to.json +1 -0
- package/locales/tr.json +1 -0
- package/locales/uk.json +1 -0
- package/locales/vi.json +1 -0
- package/locales/volto.pot +125 -18
- package/locales/zh_CN/LC_MESSAGES/volto.po +124 -17
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant.json +1 -0
- package/locales/zh_Hant_HK.json +1 -0
- package/package.json +43 -100
- package/razzle.config.js +21 -21
- package/src/actions/content/content.js +0 -1
- package/src/actions/controlpanels/controlpanels.js +13 -7
- package/src/actions/controlpanels/controlpanels.test.js +11 -5
- package/src/actions/users/users.js +2 -2
- package/src/components/manage/Actions/Actions.test.jsx +1 -5
- package/src/components/manage/Add/Add.jsx +5 -6
- package/src/components/manage/BlockChooser/BlockChooser.jsx +1 -0
- package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +1 -5
- package/src/components/manage/Blocks/Block/Edit.jsx +1 -0
- package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +9 -4
- package/src/components/manage/Blocks/Block/Settings.test.jsx +1 -5
- package/src/components/manage/Blocks/HTML/Edit.test.jsx +1 -5
- package/src/components/manage/Blocks/Image/Edit.jsx +5 -1
- package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +1 -5
- package/src/components/manage/Blocks/LeadImage/Edit.jsx +2 -2
- package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +1 -1
- package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +1 -5
- package/src/components/manage/Blocks/Listing/ImageGallery.jsx +6 -4
- package/src/components/manage/Blocks/Maps/Edit.jsx +2 -1
- package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +1 -5
- package/src/components/manage/Blocks/Search/SearchBlockView.jsx +21 -4
- package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +1 -6
- package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +1 -6
- package/src/components/manage/Blocks/Teaser/Data.jsx +21 -7
- package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +1 -1
- package/src/components/manage/Blocks/Teaser/schema.js +8 -3
- package/src/components/manage/Blocks/Video/Edit.jsx +2 -1
- package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +1 -5
- package/src/components/manage/Contents/Contents.jsx +689 -654
- package/src/components/manage/Contents/Contents.test.jsx +8 -5
- package/src/components/manage/Contents/ContentsBreadcrumbs.Multilingual.test.jsx +18 -5
- package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +20 -26
- package/src/components/manage/Contents/ContentsBreadcrumbs.test.jsx +14 -0
- package/src/components/manage/Contents/ContentsDeleteModal.jsx +258 -206
- package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +26 -8
- package/src/components/manage/Contents/ContentsItem.jsx +10 -2
- package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +1 -5
- package/src/components/manage/Contents/ContentsRenameModal.test.jsx +1 -5
- package/src/components/manage/Contents/ContentsTagsModal.test.jsx +1 -5
- package/src/components/manage/Contents/ContentsUploadModal.test.jsx +13 -22
- package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +1 -5
- package/src/components/manage/Contents/DropZoneContent.jsx +323 -0
- package/src/components/manage/Contents/__mocks__/index.tsx +2 -18
- package/src/components/manage/Controlpanels/Aliases.test.jsx +1 -5
- package/src/components/manage/Controlpanels/ContentType.jsx +1 -1
- package/src/components/manage/Controlpanels/ContentType.test.jsx +1 -5
- package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +3 -2
- package/src/components/manage/Controlpanels/Relations/Relations.jsx +1 -1
- package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +1 -5
- package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +1 -5
- package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +1 -5
- package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +156 -175
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +575 -630
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +4 -3
- package/src/components/manage/Diff/Diff.test.jsx +1 -6
- package/src/components/manage/Diff/DiffField.test.jsx +1 -6
- package/src/components/manage/Display/Display.test.jsx +2 -11
- package/src/components/manage/Edit/Edit.jsx +2 -3
- package/src/components/manage/Edit/Edit.test.jsx +1 -5
- package/src/components/manage/Form/BlockDataForm.test.jsx +1 -5
- package/src/components/manage/Form/Form.test.jsx +1 -5
- package/src/components/manage/Form/InlineForm.jsx +2 -2
- package/src/components/manage/Form/InlineForm.test.jsx +1 -5
- package/src/components/manage/Form/ModalForm.jsx +12 -10
- package/src/components/manage/Form/ModalForm.test.jsx +27 -5
- package/src/components/manage/Form/__mocks__/index.tsx +9 -27
- package/src/components/manage/Multilingual/CompareLanguages.jsx +2 -5
- package/src/components/manage/Multilingual/CreateTranslation.jsx +8 -8
- package/src/components/manage/Multilingual/ManageTranslations.jsx +4 -2
- package/src/components/manage/Multilingual/ManageTranslations.test.jsx +5 -1
- package/src/components/manage/Multilingual/TranslationObject.jsx +1 -1
- package/src/components/manage/Preferences/ChangePassword.test.jsx +1 -5
- package/src/components/manage/Preferences/PersonalPreferences.test.jsx +1 -17
- package/src/components/manage/Sidebar/ObjectBrowser.jsx +3 -0
- package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +13 -1
- package/src/components/manage/Sidebar/ObjectBrowserNav.jsx +2 -1
- package/src/components/manage/Sidebar/SidebarPortal.test.tsx +42 -0
- package/src/components/manage/Sidebar/SidebarPortal.tsx +48 -0
- package/src/components/manage/TemplateChooser/TemplateChooser.jsx +2 -1
- package/src/components/manage/Toolbar/More.jsx +4 -1
- package/src/components/manage/Toolbar/More.test.jsx +3 -0
- package/src/components/manage/Toolbar/PersonalTools.jsx +2 -1
- package/src/components/manage/Toolbar/Toolbar.jsx +3 -4
- package/src/components/manage/Toolbar/Types.jsx +7 -7
- package/src/components/manage/UniversalLink/UniversalLink.tsx +1 -0
- package/src/components/manage/Widgets/AlignWidget.stories.jsx +9 -0
- package/src/components/manage/Widgets/AlignWidget.test.tsx +95 -0
- package/src/components/manage/Widgets/{AlignWidget.jsx → AlignWidget.tsx} +23 -7
- package/src/components/manage/Widgets/ArrayWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/BlockAlignment.stories.tsx +104 -0
- package/src/components/manage/Widgets/BlockAlignment.test.tsx +104 -0
- package/src/components/manage/Widgets/BlockAlignment.tsx +88 -0
- package/src/components/manage/Widgets/BlockWidth.stories.tsx +69 -0
- package/src/components/manage/Widgets/BlockWidth.test.tsx +62 -0
- package/src/components/manage/Widgets/BlockWidth.tsx +101 -0
- package/src/components/manage/Widgets/ButtonsWidget.stories.jsx +61 -0
- package/src/components/manage/Widgets/ButtonsWidget.test.tsx +138 -0
- package/src/components/manage/Widgets/ButtonsWidget.tsx +176 -0
- package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/DatetimeWidget.jsx +16 -1
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/FileWidget.jsx +14 -8
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +146 -168
- package/src/components/manage/Widgets/ImageWidget.jsx +171 -38
- package/src/components/manage/Widgets/InternalUrlWidget.jsx +2 -0
- package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +8 -0
- package/src/components/manage/Widgets/ObjectListWidget.test.jsx +2 -11
- package/src/components/manage/Widgets/ObjectWidget.test.jsx +1 -5
- package/src/components/manage/Widgets/QueryWidget.jsx +137 -9
- package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +3 -2
- package/src/components/manage/Widgets/SchemaWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +1 -6
- package/src/components/manage/Widgets/SelectAutoComplete.jsx +29 -12
- package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +1 -6
- package/src/components/manage/Widgets/SelectWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/Size.stories.tsx +69 -0
- package/src/components/manage/Widgets/Size.test.tsx +59 -0
- package/src/components/manage/Widgets/Size.tsx +78 -0
- package/src/components/manage/Widgets/TimeWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/TokenWidget.test.jsx +1 -6
- package/src/components/manage/Widgets/UrlWidget.jsx +2 -0
- package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +2 -11
- package/src/components/manage/Widgets/__mocks__/index.tsx +33 -51
- package/src/components/manage/Widgets/index.tsx +21 -0
- package/src/components/manage/Workflow/Workflow.test.jsx +2 -11
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -3
- package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +0 -4
- package/src/components/theme/App/App.jsx +5 -1
- package/src/components/theme/App/App.test.jsx +1 -0
- package/src/components/theme/Avatar/Avatar.jsx +2 -1
- package/src/components/theme/Comments/CommentEditModal.test.jsx +1 -5
- package/src/components/theme/Comments/Comments.test.jsx +2 -11
- package/src/components/theme/ContactForm/ContactForm.test.jsx +1 -5
- package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +20 -2
- package/src/components/theme/Image/Image.jsx +11 -8
- package/src/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.tsx +7 -0
- package/src/components/theme/LanguageSelector/{LanguageSelector.test.jsx → LanguageSelector.test.tsx} +6 -6
- package/src/components/theme/LanguageSelector/LanguageSelector.tsx +89 -0
- package/src/components/theme/Logo/Logo.Multilingual.test.jsx +0 -5
- package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +10 -14
- package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +3 -5
- package/src/components/theme/Navigation/NavItem.jsx +1 -5
- package/src/components/theme/Navigation/Navigation.Multilingual.test.jsx +0 -5
- package/src/components/theme/NotFound/NotFound.jsx +5 -2
- package/src/components/theme/NotFound/NotFound.test.jsx +3 -0
- package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +1 -5
- package/src/components/theme/PreviewImage/PreviewImage.jsx +1 -1
- package/src/components/theme/Register/Register.test.jsx +1 -5
- package/src/components/theme/RequestTimeout/RequestTimeout.jsx +1 -1
- package/src/components/theme/Sitemap/Sitemap.jsx +6 -5
- package/src/components/theme/Sitemap/Sitemap.test.jsx +0 -1
- package/src/components/theme/Unauthorized/Unauthorized.jsx +5 -2
- package/src/components/theme/View/EventDatesInfo.test.jsx +1 -6
- package/src/components/theme/View/EventView.test.jsx +1 -6
- package/src/components/theme/View/FileView.jsx +9 -1
- package/src/components/theme/View/View.jsx +8 -1
- package/src/components/theme/Widgets/ImageWidget.jsx +2 -1
- package/src/config/ControlPanels.js +1 -0
- package/src/config/Widgets.jsx +7 -0
- package/src/config/index.js +18 -25
- package/src/config/server.js +0 -2
- package/src/config/slots.js +19 -0
- package/src/express-middleware/devproxy.js +20 -5
- package/src/helpers/Api/APIResourceWithAuth.js +8 -3
- package/src/helpers/Api/Api.js +7 -4
- package/src/helpers/AsyncConnect/ssr.js +4 -1
- package/src/helpers/Content/Content.js +23 -0
- package/src/helpers/Content/Content.test.js +39 -0
- package/src/helpers/Content/withClientSideContent.jsx +35 -0
- package/src/helpers/Extensions/withBlockSchemaEnhancer.jsx +4 -1
- package/src/helpers/Html/Html.jsx +13 -7
- package/src/helpers/LanguageMap/LanguageMap.js +115 -8
- package/src/helpers/Loadable/__mocks__/Loadable.jsx +7 -22
- package/src/helpers/MessageLabels/MessageLabels.js +5 -0
- package/src/helpers/Sitemap/Sitemap.js +4 -4
- package/src/helpers/Url/Url.js +33 -2
- package/src/helpers/Url/Url.test.js +62 -0
- package/src/hooks/user/useUser.js +1 -1
- package/src/internalChecks.test.ts +11 -0
- package/src/middleware/Api.test.js +4 -0
- package/src/middleware/api.js +82 -28
- package/src/middleware/storeProtectLoadUtils.test.js +3 -3
- package/src/reducers/content/content.js +3 -18
- package/src/reducers/diff/diff.js +5 -1
- package/src/reducers/diff/diff.test.js +60 -4
- package/src/reducers/querystring/querystring.js +8 -1
- package/src/routes.js +4 -2
- package/src/server.jsx +45 -14
- package/src/start-client.jsx +9 -6
- package/src/start-server.js +9 -3
- package/test-addons-loader.js +3 -0
- package/test-setup-config.jsx +0 -2
- package/test-setup-globals.js +30 -2
- package/theme/themes/pastanaga/extras/blocks.less +26 -0
- package/theme/themes/pastanaga/extras/contents.less +80 -5
- package/theme/themes/pastanaga/extras/main.less +17 -2
- package/theme/themes/pastanaga/extras/widgets.less +79 -0
- package/tsconfig.declarations.json +1 -1
- package/tsconfig.json +4 -5
- package/types/components/manage/Blocks/Teaser/schema.d.ts +1 -0
- package/types/components/manage/Contents/DropZoneContent.d.ts +2 -0
- package/types/components/manage/Contents/__mocks__/index.d.ts +2 -2
- package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
- package/types/components/manage/Controlpanels/Users/RenderUsers.d.ts +18 -2
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +6 -2
- package/types/components/manage/Controlpanels/index.d.ts +2 -2
- package/types/components/manage/Form/__mocks__/index.d.ts +8 -8
- package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
- package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
- package/types/components/manage/Sidebar/SidebarPortal.d.ts +7 -15
- package/types/components/manage/Widgets/AlignWidget.d.ts +8 -10
- package/types/components/manage/Widgets/AlignWidget.stories.d.ts +1 -0
- package/types/components/manage/Widgets/BlockAlignment.d.ts +7 -0
- package/types/components/manage/Widgets/BlockAlignment.stories.d.ts +8 -0
- package/types/components/manage/Widgets/BlockWidth.d.ts +7 -0
- package/types/components/manage/Widgets/BlockWidth.stories.d.ts +6 -0
- package/types/components/manage/Widgets/ButtonsWidget.d.ts +48 -1
- package/types/components/manage/Widgets/ButtonsWidget.stories.d.ts +3 -0
- package/types/components/manage/Widgets/FormFieldWrapper.d.ts +28 -5
- package/types/components/manage/Widgets/ImageWidget.d.ts +41 -1
- package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
- package/types/components/manage/Widgets/ObjectBrowserWidget.d.ts +2 -0
- package/types/components/manage/Widgets/QueryWidget.d.ts +5 -2
- package/types/components/manage/Widgets/RecurrenceWidget/Utils.d.ts +12 -18
- package/types/components/manage/Widgets/Size.d.ts +7 -0
- package/types/components/manage/Widgets/Size.stories.d.ts +6 -0
- package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
- package/types/components/manage/Widgets/__mocks__/index.d.ts +33 -33
- package/types/components/manage/Widgets/index.d.ts +11 -6
- package/types/components/theme/FormattedDate/FormattedDate.stories.d.ts +1 -1
- package/types/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.d.ts +3 -0
- package/types/components/theme/LanguageSelector/LanguageSelector.d.ts +3 -10
- package/types/components/theme/Unauthorized/Unauthorized.d.ts +2 -2
- package/types/config/Widgets.d.ts +6 -0
- package/types/config/slots.d.ts +7 -0
- package/types/helpers/Content/Content.d.ts +7 -0
- package/types/helpers/Content/withClientSideContent.d.ts +1 -0
- package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +4 -5
- package/types/helpers/Helmet/Helmet.d.ts +1 -1
- package/types/helpers/LanguageMap/LanguageMap.d.ts +428 -4
- package/types/helpers/Loadable/__mocks__/Loadable.d.ts +2 -2
- package/types/helpers/MessageLabels/MessageLabels.d.ts +68 -62
- package/types/helpers/Url/Url.d.ts +14 -0
- package/types/helpers/Url/bulkFlattenToAppURL.d.ts +5 -0
- package/types/middleware/api.d.ts +6 -9
- package/types/reducers/index.d.ts +1 -0
- package/types/start-client.d.ts +0 -1
- package/vitest.config.mjs +4 -4
- package/webpack-plugins/webpack-scss-plugin.js +172 -0
- package/jest-addons-loader.js +0 -3
- package/jest-extender-plugin.js +0 -39
- package/jest-setup-afterenv.js +0 -2
- package/jest-svgsystem-transform.js +0 -10
- package/package-why.json +0 -34
- package/patches/patchit.sh +0 -2
- package/patches/razzle-jest.patch +0 -10
- package/src/actions/content/content.multilingual.test.js +0 -17
- package/src/components/manage/Contents/__mocks__/index.vitest.tsx +0 -5
- package/src/components/manage/Form/__mocks__/index.vitest.tsx +0 -73
- package/src/components/manage/Sidebar/SidebarPortal.jsx +0 -47
- package/src/components/manage/Sidebar/SidebarPortal.test.jsx +0 -26
- package/src/components/manage/Widgets/AlignWidget.test.jsx +0 -59
- package/src/components/manage/Widgets/ButtonsWidget.jsx +0 -41
- package/src/components/manage/Widgets/ButtonsWidget.test.jsx +0 -70
- package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +0 -41
- package/src/components/theme/LanguageSelector/LanguageSelector.jsx +0 -77
- package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +0 -39
- package/test-setup-globals-vitest.js +0 -46
- package/theme/themes/pastanaga/extras/utils.less +0 -63
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
normaliseMail,
|
|
20
20
|
normalizeTelephone,
|
|
21
21
|
flattenScales,
|
|
22
|
+
addSubpathPrefix,
|
|
23
|
+
stripSubpathPrefix,
|
|
22
24
|
} from './Url';
|
|
23
25
|
|
|
24
26
|
beforeEach(() => {
|
|
@@ -533,4 +535,64 @@ describe('Url', () => {
|
|
|
533
535
|
});
|
|
534
536
|
});
|
|
535
537
|
});
|
|
538
|
+
|
|
539
|
+
describe('Subpath tests', () => {
|
|
540
|
+
beforeEach(() => {
|
|
541
|
+
settings.subpathPrefix = '/site';
|
|
542
|
+
});
|
|
543
|
+
describe('addSubpathPrefix', () => {
|
|
544
|
+
it('adds subpath prefix to internal URLs', () => {
|
|
545
|
+
expect(addSubpathPrefix('/some-page')).toBe('/site/some-page');
|
|
546
|
+
expect(addSubpathPrefix('/news/article')).toBe('/site/news/article');
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it('does not add subpath prefix to URLs that already have it', () => {
|
|
550
|
+
expect(addSubpathPrefix('/site/some-page')).toBe('/site/some-page');
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it('does not add subpath prefix to external URLs', () => {
|
|
554
|
+
expect(addSubpathPrefix('https://example.com/page')).toBe(
|
|
555
|
+
'https://example.com/page',
|
|
556
|
+
);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('handles empty subpath prefix', () => {
|
|
560
|
+
settings.subpathPrefix = '';
|
|
561
|
+
expect(addSubpathPrefix('/some-page')).toBe('/some-page');
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it('handles undefined subpath prefix', () => {
|
|
565
|
+
settings.subpathPrefix = undefined;
|
|
566
|
+
expect(addSubpathPrefix('/some-page')).toBe('/some-page');
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
describe('stripSubpathPrefix', () => {
|
|
571
|
+
beforeEach(() => {
|
|
572
|
+
settings.subpathPrefix = '/site';
|
|
573
|
+
});
|
|
574
|
+
it('removes subpath prefix from URLs that have it', () => {
|
|
575
|
+
expect(stripSubpathPrefix('/site/some-page')).toBe('/some-page');
|
|
576
|
+
expect(stripSubpathPrefix('/site/news/article')).toBe('/news/article');
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
it('leaves URLs unchanged if they do not have the prefix', () => {
|
|
580
|
+
expect(stripSubpathPrefix('/other/some-page')).toBe('/other/some-page');
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('handles the case where URL is exactly the subpath prefix', () => {
|
|
584
|
+
expect(stripSubpathPrefix('/site')).toBe('');
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it('handles empty subpath prefix', () => {
|
|
588
|
+
settings.subpathPrefix = '';
|
|
589
|
+
expect(stripSubpathPrefix('/some-page')).toBe('/some-page');
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('handles undefined subpath prefix', () => {
|
|
593
|
+
settings.subpathPrefix = undefined;
|
|
594
|
+
expect(stripSubpathPrefix('/some-page')).toBe('/some-page');
|
|
595
|
+
});
|
|
596
|
+
});
|
|
597
|
+
});
|
|
536
598
|
});
|
|
@@ -12,7 +12,7 @@ const useUser = () => {
|
|
|
12
12
|
const dispatch = useDispatch();
|
|
13
13
|
|
|
14
14
|
useEffect(() => {
|
|
15
|
-
if (!user?.id && users?.get.loading === false) {
|
|
15
|
+
if (userId && !user?.id && users?.get.loading === false) {
|
|
16
16
|
dispatch(getUser(userId));
|
|
17
17
|
}
|
|
18
18
|
}, [dispatch, userId, user, users?.get.loading]);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import packageJson from '../package.json';
|
|
3
|
+
|
|
4
|
+
describe('internal checks', () => {
|
|
5
|
+
it('keeps prettier listed as a runtime dependency', () => {
|
|
6
|
+
const dependencies = packageJson.dependencies ?? {};
|
|
7
|
+
|
|
8
|
+
expect(dependencies).toHaveProperty('prettier');
|
|
9
|
+
expect(typeof dependencies.prettier).toBe('string');
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -25,6 +25,8 @@ describe('api middleware helpers', () => {
|
|
|
25
25
|
const result = addExpandersToPath(
|
|
26
26
|
'/de/mypage?expand=translations',
|
|
27
27
|
GET_CONTENT,
|
|
28
|
+
false,
|
|
29
|
+
true,
|
|
28
30
|
);
|
|
29
31
|
expect(result).toEqual('/de/mypage?expand=translations,mycustomexpander');
|
|
30
32
|
});
|
|
@@ -183,6 +185,8 @@ describe('api middleware helpers', () => {
|
|
|
183
185
|
const result = addExpandersToPath(
|
|
184
186
|
'/de/mypage/@navigation?expand=translations&expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
185
187
|
GET_CONTENT,
|
|
188
|
+
false,
|
|
189
|
+
true,
|
|
186
190
|
);
|
|
187
191
|
// No need to stringify
|
|
188
192
|
expect(result).toEqual(
|
package/src/middleware/api.js
CHANGED
|
@@ -35,7 +35,7 @@ let socket = null;
|
|
|
35
35
|
*
|
|
36
36
|
* - It should add the expanders set in the config settings
|
|
37
37
|
* - It should preserve any query if present
|
|
38
|
-
* - It should preserve (and add) any expand parameter (if present)
|
|
38
|
+
* - It should preserve (and add) any expand parameter (if present)
|
|
39
39
|
* - It should take use the correct codification for arrays in querystring (repeated parameter for each member of the array)
|
|
40
40
|
*
|
|
41
41
|
* @function addExpandersToPath
|
|
@@ -43,7 +43,7 @@ let socket = null;
|
|
|
43
43
|
* @param {*} type The action type
|
|
44
44
|
* @returns {string} The url/path with the configured expanders added to the query string
|
|
45
45
|
*/
|
|
46
|
-
export function addExpandersToPath(path, type, isAnonymous) {
|
|
46
|
+
export function addExpandersToPath(path, type, isAnonymous, isMultilingual) {
|
|
47
47
|
const { settings } = config;
|
|
48
48
|
const { apiExpanders = [] } = settings;
|
|
49
49
|
|
|
@@ -58,7 +58,14 @@ export function addExpandersToPath(path, type, isAnonymous) {
|
|
|
58
58
|
|
|
59
59
|
const expandMerge = compact(
|
|
60
60
|
union([expand, ...flatten(expandersFromConfig)]),
|
|
61
|
-
).filter(
|
|
61
|
+
).filter(
|
|
62
|
+
// Remove types for anonymous, translations unless multilingual
|
|
63
|
+
(item) =>
|
|
64
|
+
!(
|
|
65
|
+
(item === 'types' && isAnonymous) ||
|
|
66
|
+
(item === 'translations' && !isMultilingual)
|
|
67
|
+
),
|
|
68
|
+
);
|
|
62
69
|
|
|
63
70
|
const stringifiedExpand = qs.stringify(
|
|
64
71
|
{ expand: expandMerge },
|
|
@@ -128,6 +135,8 @@ function sendOnSocket(request) {
|
|
|
128
135
|
* @param {Object} api Api object.
|
|
129
136
|
* @returns {Promise} Action promise.
|
|
130
137
|
*/
|
|
138
|
+
let isHydrating = __CLIENT__ ? true : false;
|
|
139
|
+
|
|
131
140
|
const apiMiddlewareFactory =
|
|
132
141
|
(api) =>
|
|
133
142
|
({ dispatch, getState }) =>
|
|
@@ -135,14 +144,17 @@ const apiMiddlewareFactory =
|
|
|
135
144
|
(action) => {
|
|
136
145
|
const { settings } = config;
|
|
137
146
|
|
|
138
|
-
const
|
|
139
|
-
|
|
147
|
+
const state = getState();
|
|
148
|
+
const token = state.userSession.token;
|
|
149
|
+
let uploadedFiles = state.content.uploadedFiles;
|
|
150
|
+
const isMultilingual = state.site.data.features?.multilingual;
|
|
140
151
|
let isAnonymous = true;
|
|
141
152
|
if (token) {
|
|
142
153
|
const tokenExpiration = jwtDecode(token).exp;
|
|
143
154
|
const currentTime = new Date().getTime() / 1000;
|
|
144
155
|
isAnonymous = !token || currentTime > tokenExpiration;
|
|
145
156
|
}
|
|
157
|
+
const hasExistingError = state.content.get?.error;
|
|
146
158
|
|
|
147
159
|
if (typeof action === 'function') {
|
|
148
160
|
return action(dispatch, getState);
|
|
@@ -164,14 +176,24 @@ const apiMiddlewareFactory =
|
|
|
164
176
|
request.map((item) =>
|
|
165
177
|
sendOnSocket({
|
|
166
178
|
...item,
|
|
167
|
-
path: addExpandersToPath(
|
|
179
|
+
path: addExpandersToPath(
|
|
180
|
+
item.path,
|
|
181
|
+
type,
|
|
182
|
+
isAnonymous,
|
|
183
|
+
isMultilingual,
|
|
184
|
+
),
|
|
168
185
|
id: type,
|
|
169
186
|
}),
|
|
170
187
|
),
|
|
171
188
|
)
|
|
172
189
|
: sendOnSocket({
|
|
173
190
|
...request,
|
|
174
|
-
path: addExpandersToPath(
|
|
191
|
+
path: addExpandersToPath(
|
|
192
|
+
request.path,
|
|
193
|
+
type,
|
|
194
|
+
isAnonymous,
|
|
195
|
+
isMultilingual,
|
|
196
|
+
),
|
|
175
197
|
id: type,
|
|
176
198
|
});
|
|
177
199
|
} else {
|
|
@@ -180,7 +202,12 @@ const apiMiddlewareFactory =
|
|
|
180
202
|
? request.reduce((prevPromise, item) => {
|
|
181
203
|
return prevPromise.then((acc) => {
|
|
182
204
|
return api[item.op](
|
|
183
|
-
addExpandersToPath(
|
|
205
|
+
addExpandersToPath(
|
|
206
|
+
item.path,
|
|
207
|
+
type,
|
|
208
|
+
isAnonymous,
|
|
209
|
+
isMultilingual,
|
|
210
|
+
),
|
|
184
211
|
{
|
|
185
212
|
data: item.data,
|
|
186
213
|
type: item.type,
|
|
@@ -201,28 +228,42 @@ const apiMiddlewareFactory =
|
|
|
201
228
|
}, Promise.resolve([]))
|
|
202
229
|
: Promise.all(
|
|
203
230
|
request.map((item) =>
|
|
204
|
-
api[item.op](
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
action.type,
|
|
231
|
+
api[item.op](
|
|
232
|
+
addExpandersToPath(
|
|
233
|
+
item.path,
|
|
234
|
+
type,
|
|
235
|
+
isAnonymous,
|
|
236
|
+
isMultilingual,
|
|
211
237
|
),
|
|
212
|
-
|
|
213
|
-
|
|
238
|
+
{
|
|
239
|
+
data: item.data,
|
|
240
|
+
type: item.type,
|
|
241
|
+
headers: item.headers,
|
|
242
|
+
params: request.params,
|
|
243
|
+
checkUrl: settings.actions_raising_api_errors.includes(
|
|
244
|
+
action.type,
|
|
245
|
+
),
|
|
246
|
+
attach: item.attach,
|
|
247
|
+
},
|
|
248
|
+
),
|
|
214
249
|
),
|
|
215
250
|
)
|
|
216
|
-
: api[request.op](
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
251
|
+
: api[request.op](
|
|
252
|
+
addExpandersToPath(request.path, type, isAnonymous, isMultilingual),
|
|
253
|
+
{
|
|
254
|
+
data: request.data,
|
|
255
|
+
type: request.type,
|
|
256
|
+
headers: request.headers,
|
|
257
|
+
params: request.params,
|
|
258
|
+
checkUrl: settings.actions_raising_api_errors.includes(
|
|
259
|
+
action.type,
|
|
260
|
+
),
|
|
261
|
+
attach: request.attach,
|
|
262
|
+
},
|
|
263
|
+
);
|
|
224
264
|
actionPromise.then(
|
|
225
265
|
(result) => {
|
|
266
|
+
isHydrating = false;
|
|
226
267
|
if (uploadedFiles !== 0) {
|
|
227
268
|
dispatch(updateUploadedFiles(0));
|
|
228
269
|
}
|
|
@@ -298,8 +339,21 @@ const apiMiddlewareFactory =
|
|
|
298
339
|
}
|
|
299
340
|
},
|
|
300
341
|
(error) => {
|
|
342
|
+
// Make sure an error during hydration
|
|
343
|
+
// (for example when serving an archived page)
|
|
344
|
+
// doesn't hide the SSR content. Only suppress GET_CONTENT failures;
|
|
345
|
+
// user-initiated actions (LOGIN, etc.) must always dispatch _FAIL so
|
|
346
|
+
// loaders stop and errors surface.
|
|
347
|
+
const shouldIgnoreHydrationError =
|
|
348
|
+
isHydrating && !hasExistingError && type === GET_CONTENT;
|
|
349
|
+
|
|
350
|
+
if (shouldIgnoreHydrationError) {
|
|
351
|
+
isHydrating = false;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
301
355
|
// Only SSR can set ECONNREFUSED
|
|
302
|
-
if (error
|
|
356
|
+
if (error?.code === 'ECONNREFUSED') {
|
|
303
357
|
next({
|
|
304
358
|
...rest,
|
|
305
359
|
error,
|
|
@@ -310,7 +364,7 @@ const apiMiddlewareFactory =
|
|
|
310
364
|
}
|
|
311
365
|
|
|
312
366
|
// Response error is marked crossDomain if CORS error happen
|
|
313
|
-
else if (error
|
|
367
|
+
else if (error?.crossDomain) {
|
|
314
368
|
next({
|
|
315
369
|
...rest,
|
|
316
370
|
error,
|
|
@@ -361,7 +415,7 @@ const apiMiddlewareFactory =
|
|
|
361
415
|
...rest,
|
|
362
416
|
error,
|
|
363
417
|
statusCode: error.response,
|
|
364
|
-
message: error.response
|
|
418
|
+
message: error.response?.body?.message,
|
|
365
419
|
connectionRefused: false,
|
|
366
420
|
type: SET_APIERROR,
|
|
367
421
|
});
|
|
@@ -445,9 +445,9 @@ describe('storeProtectLoadUtils', () => {
|
|
|
445
445
|
isCounting: false,
|
|
446
446
|
});
|
|
447
447
|
};
|
|
448
|
-
test('pending', expectPass({ type: 'ANY_PENDING' }
|
|
449
|
-
test('success', expectPass({ type: 'ANY_SUCCESS' }
|
|
450
|
-
test('failure', expectPass({ type: 'ANY_FAIL' }
|
|
448
|
+
test('pending', expectPass({ type: 'ANY_PENDING' }, 2));
|
|
449
|
+
test('success', expectPass({ type: 'ANY_SUCCESS' }, 2));
|
|
450
|
+
test('failure', expectPass({ type: 'ANY_FAIL' }, 2));
|
|
451
451
|
});
|
|
452
452
|
describe('counting', () => {
|
|
453
453
|
const expectCount = (action, from, to) => () => {
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
* @module reducers/content/content
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import map from 'lodash/map';
|
|
7
|
-
import mapKeys from 'lodash/mapKeys';
|
|
8
6
|
import omit from 'lodash/omit';
|
|
9
7
|
|
|
10
8
|
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
9
|
+
import { flattenStaticBehaviors } from '@plone/volto/helpers/Content/Content';
|
|
11
10
|
|
|
12
11
|
import {
|
|
13
12
|
CREATE_CONTENT,
|
|
@@ -131,14 +130,7 @@ export default function content(state = initialState, action = {}) {
|
|
|
131
130
|
},
|
|
132
131
|
};
|
|
133
132
|
case `${CREATE_CONTENT}_SUCCESS`:
|
|
134
|
-
|
|
135
|
-
map(result['@static_behaviors'], (behavior) => {
|
|
136
|
-
result = {
|
|
137
|
-
...omit(result, behavior),
|
|
138
|
-
...mapKeys(result[behavior], (value, key) => `${behavior}.${key}`),
|
|
139
|
-
};
|
|
140
|
-
});
|
|
141
|
-
}
|
|
133
|
+
result = flattenStaticBehaviors(result);
|
|
142
134
|
const data = action.subrequest
|
|
143
135
|
? Array.isArray(result)
|
|
144
136
|
? result.map((item) => ({
|
|
@@ -188,14 +180,7 @@ export default function content(state = initialState, action = {}) {
|
|
|
188
180
|
},
|
|
189
181
|
};
|
|
190
182
|
case `${GET_CONTENT}_SUCCESS`:
|
|
191
|
-
|
|
192
|
-
map(result['@static_behaviors'], (behavior) => {
|
|
193
|
-
result = {
|
|
194
|
-
...omit(result, behavior),
|
|
195
|
-
...mapKeys(result[behavior], (value, key) => `${behavior}.${key}`),
|
|
196
|
-
};
|
|
197
|
-
});
|
|
198
|
-
}
|
|
183
|
+
result = flattenStaticBehaviors(result);
|
|
199
184
|
|
|
200
185
|
const transforms = config.getUtilities({
|
|
201
186
|
type: 'transform',
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { GET_DIFF } from '@plone/volto/constants/ActionTypes';
|
|
7
|
+
import { flattenStaticBehaviors } from '@plone/volto/helpers/Content/Content';
|
|
7
8
|
|
|
8
9
|
const initialState = {
|
|
9
10
|
error: null,
|
|
@@ -29,10 +30,13 @@ export default function diff(state = initialState, action = {}) {
|
|
|
29
30
|
loading: true,
|
|
30
31
|
};
|
|
31
32
|
case `${GET_DIFF}_SUCCESS`:
|
|
33
|
+
const first_result = flattenStaticBehaviors(action.result[0]);
|
|
34
|
+
const second_result = flattenStaticBehaviors(action.result[1]);
|
|
35
|
+
|
|
32
36
|
return {
|
|
33
37
|
...state,
|
|
34
38
|
error: null,
|
|
35
|
-
data:
|
|
39
|
+
data: [first_result, second_result],
|
|
36
40
|
loaded: true,
|
|
37
41
|
loading: false,
|
|
38
42
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import diff from './diff';
|
|
2
1
|
import { GET_DIFF } from '@plone/volto/constants/ActionTypes';
|
|
2
|
+
import diff from './diff';
|
|
3
3
|
|
|
4
4
|
describe('Diff reducer', () => {
|
|
5
5
|
it('should return the initial state', () => {
|
|
@@ -24,15 +24,71 @@ describe('Diff reducer', () => {
|
|
|
24
24
|
});
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
it('should handle GET_DIFF_SUCCESS', () => {
|
|
27
|
+
it('should handle GET_DIFF_SUCCESS with array result with static behaviors', () => {
|
|
28
|
+
expect(
|
|
29
|
+
diff(undefined, {
|
|
30
|
+
type: `${GET_DIFF}_SUCCESS`,
|
|
31
|
+
result: [
|
|
32
|
+
{
|
|
33
|
+
'@static_behaviors': [
|
|
34
|
+
'guillotina.behaviors.dublincore.IDublinCore',
|
|
35
|
+
],
|
|
36
|
+
'guillotina.behaviors.dublincore.IDublinCore': {
|
|
37
|
+
title: 'test page',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
'@static_behaviors': [
|
|
42
|
+
'guillotina.behaviors.dublincore.IDublinCore',
|
|
43
|
+
],
|
|
44
|
+
'guillotina.behaviors.dublincore.IDublinCore': {
|
|
45
|
+
title: 'test second page',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
}),
|
|
50
|
+
).toEqual({
|
|
51
|
+
error: null,
|
|
52
|
+
data: [
|
|
53
|
+
{
|
|
54
|
+
'@static_behaviors': ['guillotina.behaviors.dublincore.IDublinCore'],
|
|
55
|
+
|
|
56
|
+
'guillotina.behaviors.dublincore.IDublinCore.title': 'test page',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
'@static_behaviors': ['guillotina.behaviors.dublincore.IDublinCore'],
|
|
60
|
+
'guillotina.behaviors.dublincore.IDublinCore.title':
|
|
61
|
+
'test second page',
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
loaded: true,
|
|
65
|
+
loading: false,
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should handle GET_DIFF_SUCCESS with array result without static behaviors', () => {
|
|
70
|
+
const data = [
|
|
71
|
+
{
|
|
72
|
+
title: 'test page',
|
|
73
|
+
'guillotina.behaviors.dublincore.IDublinCore': {
|
|
74
|
+
title: 'test page',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: 'test second page',
|
|
79
|
+
'guillotina.behaviors.dublincore.IDublinCore': {
|
|
80
|
+
title: 'test second page',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
];
|
|
28
84
|
expect(
|
|
29
85
|
diff(undefined, {
|
|
30
86
|
type: `${GET_DIFF}_SUCCESS`,
|
|
31
|
-
result:
|
|
87
|
+
result: data,
|
|
32
88
|
}),
|
|
33
89
|
).toEqual({
|
|
34
90
|
error: null,
|
|
35
|
-
data:
|
|
91
|
+
data: data,
|
|
36
92
|
loaded: true,
|
|
37
93
|
loading: false,
|
|
38
94
|
});
|
|
@@ -30,10 +30,17 @@ export default function querystring(state = initialState, action = {}) {
|
|
|
30
30
|
loading: true,
|
|
31
31
|
};
|
|
32
32
|
case `${GET_QUERYSTRING}_SUCCESS`:
|
|
33
|
+
let indexes = action.result.indexes;
|
|
34
|
+
if (indexes?.path?.operations) {
|
|
35
|
+
//remove path operation, to remove unhandled 'Navigation path' option from QueryWidget
|
|
36
|
+
indexes.path.operations = indexes.path.operations.filter(
|
|
37
|
+
(o) => o !== 'plone.app.querystring.operation.string.path',
|
|
38
|
+
);
|
|
39
|
+
}
|
|
33
40
|
return {
|
|
34
41
|
...state,
|
|
35
42
|
error: null,
|
|
36
|
-
indexes:
|
|
43
|
+
indexes: indexes,
|
|
37
44
|
sortable_indexes: action.result.sortable_indexes,
|
|
38
45
|
loaded: true,
|
|
39
46
|
loading: false,
|
package/src/routes.js
CHANGED
|
@@ -52,6 +52,8 @@ import {
|
|
|
52
52
|
UpgradeControlPanel,
|
|
53
53
|
} from '@plone/volto/components/manage/Controlpanels';
|
|
54
54
|
|
|
55
|
+
import withClientSideContent from '@plone/volto/helpers/Content/withClientSideContent';
|
|
56
|
+
|
|
55
57
|
import App from '@plone/volto/components/theme/App/App';
|
|
56
58
|
import View from '@plone/volto/components/theme/View/View';
|
|
57
59
|
|
|
@@ -127,7 +129,7 @@ export function getExternalRoutes() {
|
|
|
127
129
|
export const defaultRoutes = [
|
|
128
130
|
// redirect to external links if path is in blacklist
|
|
129
131
|
...getExternalRoutes(),
|
|
130
|
-
...(
|
|
132
|
+
...(config.settings?.isMultilingual !== false ? multilingualRoutes : []),
|
|
131
133
|
{
|
|
132
134
|
path: '/',
|
|
133
135
|
component: View,
|
|
@@ -244,7 +246,7 @@ export const defaultRoutes = [
|
|
|
244
246
|
},
|
|
245
247
|
{
|
|
246
248
|
path: ['/edit', '/**/edit'],
|
|
247
|
-
component: Edit,
|
|
249
|
+
component: withClientSideContent(Edit),
|
|
248
250
|
},
|
|
249
251
|
{
|
|
250
252
|
path: ['/contents', '/**/contents'],
|
package/src/server.jsx
CHANGED
|
@@ -18,8 +18,9 @@ import { CookiesProvider } from 'react-cookie';
|
|
|
18
18
|
import cookiesMiddleware from 'universal-cookie-express';
|
|
19
19
|
import debug from 'debug';
|
|
20
20
|
|
|
21
|
-
import routes from '@
|
|
21
|
+
import routes from '@plone/volto/routes';
|
|
22
22
|
import config from '@plone/volto/registry';
|
|
23
|
+
import okMiddleware from '@plone/volto/express-middleware/ok';
|
|
23
24
|
|
|
24
25
|
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
25
26
|
import Html from '@plone/volto/helpers/Html/Html';
|
|
@@ -39,10 +40,14 @@ import ErrorPage from '@plone/volto/error';
|
|
|
39
40
|
import languages from '@plone/volto/constants/Languages.cjs';
|
|
40
41
|
|
|
41
42
|
import configureStore from '@plone/volto/store';
|
|
42
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
ReduxAsyncConnect,
|
|
45
|
+
loadOnServer,
|
|
46
|
+
} from '@plone/volto/helpers/AsyncConnect';
|
|
43
47
|
|
|
44
48
|
let locales = {};
|
|
45
49
|
|
|
50
|
+
// Load locales listed in supportedLanguages setting
|
|
46
51
|
if (config.settings) {
|
|
47
52
|
config.settings.supportedLanguages.forEach((lang) => {
|
|
48
53
|
const langFileName = toGettextLang(lang);
|
|
@@ -68,10 +73,30 @@ const server = express()
|
|
|
68
73
|
})
|
|
69
74
|
.use(cookiesMiddleware());
|
|
70
75
|
|
|
76
|
+
// If Volto is being served under a subpath,
|
|
77
|
+
// make sure the static files are available there too.
|
|
78
|
+
// (The static middleware loads too early to access the config.)
|
|
79
|
+
if (config.settings.subpathPrefix) {
|
|
80
|
+
server.use(
|
|
81
|
+
config.settings.subpathPrefix,
|
|
82
|
+
express.static(
|
|
83
|
+
process.env.BUILD_DIR
|
|
84
|
+
? path.join(process.env.BUILD_DIR, 'public')
|
|
85
|
+
: process.env.RAZZLE_PUBLIC_DIR,
|
|
86
|
+
{
|
|
87
|
+
redirect: false, // Avoid /my-prefix from being redirected to /my-prefix/
|
|
88
|
+
},
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
71
93
|
const middleware = (config.settings.expressMiddleware || []).filter((m) => m);
|
|
72
94
|
|
|
73
95
|
server.all('*', setupServer);
|
|
74
|
-
if (middleware.length)
|
|
96
|
+
if (middleware.length) {
|
|
97
|
+
server.use(config.settings.subpathPrefix || '/', middleware);
|
|
98
|
+
}
|
|
99
|
+
server.use('/', okMiddleware());
|
|
75
100
|
|
|
76
101
|
server.use(function (err, req, res, next) {
|
|
77
102
|
if (err) {
|
|
@@ -107,7 +132,6 @@ function setupServer(req, res, next) {
|
|
|
107
132
|
const lang = toReactIntlLang(
|
|
108
133
|
new locale.Locales(
|
|
109
134
|
req.universalCookies.get('I18N_LANGUAGE') ||
|
|
110
|
-
config.settings.defaultLanguage ||
|
|
111
135
|
req.headers['accept-language'],
|
|
112
136
|
)
|
|
113
137
|
.best(supported)
|
|
@@ -160,8 +184,10 @@ function setupServer(req, res, next) {
|
|
|
160
184
|
res.locals.detectedHost = `${
|
|
161
185
|
req.headers['x-forwarded-proto'] || req.protocol
|
|
162
186
|
}://${req.headers.host}`;
|
|
163
|
-
config.settings.apiPath =
|
|
164
|
-
|
|
187
|
+
config.settings.apiPath =
|
|
188
|
+
res.locals.detectedHost + config.settings.subpathPrefix;
|
|
189
|
+
config.settings.publicURL =
|
|
190
|
+
res.locals.detectedHost + config.settings.subpathPrefix;
|
|
165
191
|
}
|
|
166
192
|
|
|
167
193
|
res.locals = {
|
|
@@ -184,7 +210,6 @@ server.get('/*', (req, res) => {
|
|
|
184
210
|
const lang = toReactIntlLang(
|
|
185
211
|
new locale.Locales(
|
|
186
212
|
req.universalCookies.get('I18N_LANGUAGE') ||
|
|
187
|
-
config.settings.defaultLanguage ||
|
|
188
213
|
req.headers['accept-language'],
|
|
189
214
|
)
|
|
190
215
|
.best(supported)
|
|
@@ -224,9 +249,10 @@ server.get('/*', (req, res) => {
|
|
|
224
249
|
|
|
225
250
|
loadOnServer({ store, location, routes, api })
|
|
226
251
|
.then(() => {
|
|
252
|
+
const state = store.getState();
|
|
227
253
|
const initialLang =
|
|
228
254
|
req.universalCookies.get('I18N_LANGUAGE') ||
|
|
229
|
-
|
|
255
|
+
state.site.data['plone.default_language'] ||
|
|
230
256
|
req.headers['accept-language'];
|
|
231
257
|
|
|
232
258
|
// The content info is in the store at this point thanks to the asynconnect
|
|
@@ -236,10 +262,9 @@ server.get('/*', (req, res) => {
|
|
|
236
262
|
// TODO: there is a bug here with content that, for any reason, doesn't
|
|
237
263
|
// present the language token field, for some reason. In this case, we
|
|
238
264
|
// should follow the cookie rather then switching the language
|
|
239
|
-
const contentLang =
|
|
265
|
+
const contentLang = state.content.get?.error
|
|
240
266
|
? initialLang
|
|
241
|
-
:
|
|
242
|
-
config.settings.defaultLanguage;
|
|
267
|
+
: state.content.data?.language?.token || initialLang;
|
|
243
268
|
|
|
244
269
|
if (toBackendLang(initialLang) !== contentLang && url !== '/') {
|
|
245
270
|
const newLang = toReactIntlLang(
|
|
@@ -254,7 +279,11 @@ server.get('/*', (req, res) => {
|
|
|
254
279
|
<ChunkExtractorManager extractor={extractor}>
|
|
255
280
|
<CookiesProvider cookies={req.universalCookies}>
|
|
256
281
|
<Provider store={store} onError={reactIntlErrorHandler}>
|
|
257
|
-
<StaticRouter
|
|
282
|
+
<StaticRouter
|
|
283
|
+
context={context}
|
|
284
|
+
location={req.url}
|
|
285
|
+
basename={config.settings.subpathPrefix}
|
|
286
|
+
>
|
|
258
287
|
<ReduxAsyncConnect routes={routes} helpers={api} />
|
|
259
288
|
</StaticRouter>
|
|
260
289
|
</Provider>
|
|
@@ -291,8 +320,8 @@ server.get('/*', (req, res) => {
|
|
|
291
320
|
markup={markup}
|
|
292
321
|
store={store}
|
|
293
322
|
criticalCss={readCriticalCss(req)}
|
|
294
|
-
apiPath={
|
|
295
|
-
publicURL={
|
|
323
|
+
apiPath={config.settings.apiPath}
|
|
324
|
+
publicURL={config.settings.publicURL}
|
|
296
325
|
/>,
|
|
297
326
|
)}
|
|
298
327
|
`,
|
|
@@ -335,6 +364,8 @@ export const defaultReadCriticalCss = () => {
|
|
|
335
364
|
|
|
336
365
|
// Exposed for the console bootstrap info messages
|
|
337
366
|
server.apiPath = config.settings.apiPath;
|
|
367
|
+
server.internalApiPath = config.settings.internalApiPath;
|
|
368
|
+
server.subpathPrefix = config.settings.subpathPrefix;
|
|
338
369
|
server.devProxyToApiPath = config.settings.devProxyToApiPath;
|
|
339
370
|
server.proxyRewriteTarget = config.settings.proxyRewriteTarget;
|
|
340
371
|
server.publicURL = config.settings.publicURL;
|