diff --git a/packages/core/admin/admin/src/StrapiApp.js b/packages/core/admin/admin/src/StrapiApp.js index 117accf157..36867db510 100644 --- a/packages/core/admin/admin/src/StrapiApp.js +++ b/packages/core/admin/admin/src/StrapiApp.js @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { darkTheme, lightTheme } from '@strapi/design-system'; import invariant from 'invariant'; @@ -114,30 +114,14 @@ class StrapiApp { ); invariant( link.Component && typeof link.Component === 'function', - `link.Component must be a function returning a Promise. Please use: \`Component: () => import(path)\` instead.` + `link.Component should be a valid React Component` ); invariant( link.icon && typeof link.icon === 'function', `link.Icon should be a valid React Component` ); - if ( - link.Component && - typeof link.Component === 'function' && - link.Component[Symbol.toStringTag] === 'AsyncFunction' - ) { - console.warn(` - [deprecated] addMenuLink() was called with an async Component from the plugin "${link.intlLabel.Internationalization}". This will be removed - in the future. Please use: \`Component: () => import(path)\` instead. - `); - } - - this.menu.push({ - ...link, - - // React.lazy can be removed once we migrate to react-router@6, because the component can handle it natively - Component: React.lazy(link.Component), - }); + this.menu.push(link); }; addMiddlewares = (middlewares) => { @@ -165,26 +149,10 @@ class StrapiApp { invariant(link.to, `link.to should be defined for ${stringifiedLink}`); invariant( link.Component && typeof link.Component === 'function', - `link.Component must be a function returning a Promise. Please use: \`Component: () => import(path)\` instead.` + `link.Component should be a valid React Component` ); - if ( - link.Component && - typeof link.Component === 'function' && - link.Component[Symbol.toStringTag] === 'AsyncFunction' - ) { - console.warn(` - [deprecated] addSettingsLink() was called with an async Component from the plugin: "${link.intlLabel.Internationalization}". This will be removed - in the future. Please use: \`Component: () => import(path)\` instead. - `); - } - - this.settings[sectionId].links.push({ - ...link, - - // React.lazy can be removed once we migrate to react-router@6, because the component can handle it natively - Component: React.lazy(link.Component), - }); + this.settings[sectionId].links.push(link); }; addSettingsLinks = (sectionId, links) => { diff --git a/packages/core/admin/admin/src/components/Providers/index.js b/packages/core/admin/admin/src/components/Providers/index.js index e7c10d5738..412891cbc7 100644 --- a/packages/core/admin/admin/src/components/Providers/index.js +++ b/packages/core/admin/admin/src/components/Providers/index.js @@ -111,8 +111,7 @@ Providers.propTypes = { defaultMessage: PropTypes.string.isRequired, }).isRequired, permissions: PropTypes.array, - // React.lazy loadable - Component: PropTypes.object, + Component: PropTypes.func, }) ).isRequired, menuLogo: PropTypes.oneOfType([PropTypes.string, PropTypes.any]).isRequired, diff --git a/packages/core/admin/admin/src/pages/Admin/index.js b/packages/core/admin/admin/src/pages/Admin/index.js index 2463a7f54d..dd0129a3d1 100644 --- a/packages/core/admin/admin/src/pages/Admin/index.js +++ b/packages/core/admin/admin/src/pages/Admin/index.js @@ -16,6 +16,7 @@ import { Route, Switch } from 'react-router-dom'; import LeftMenu from '../../components/LeftMenu'; import useConfigurations from '../../hooks/useConfigurations'; import useMenu from '../../hooks/useMenu'; +import { createRoute } from '../../utils/createRoute'; import { SET_APP_RUNTIME_STATUS } from '../App/constants'; const CM = React.lazy(() => @@ -75,6 +76,25 @@ export const Admin = () => { } }, [appStatus, dispatch, trackUsage]); + const routes = menu + .filter((link) => link.Component) + + /** + * `Component` is an async function, which is passed as property of the + * addMenuLink() API during the plugin registration step. + * + * Because of that we can't just render , + * but have to await the function. + * + * This isn't a good React pattern and should be reconsidered. + */ + + .map(({ to, Component, exact }) => createRoute(Component, to, exact)); + + if (isLoading) { + return ; + } + return ( @@ -84,31 +104,18 @@ export const Admin = () => { /> - {isLoading ? ( - - ) : ( + }> - {menu.map(({ to, Component, exact }) => ( - ( - }> - - - )} - key={to} - path={to} - exact={exact || false} - /> - ))} + {routes} - )} + {/* TODO: we should move the logic to determine whether the guided tour is displayed diff --git a/packages/core/admin/admin/src/pages/SettingsPage/constants.js b/packages/core/admin/admin/src/pages/SettingsPage/constants.js index 3aaf3315c8..2ade0f5bbf 100644 --- a/packages/core/admin/admin/src/pages/SettingsPage/constants.js +++ b/packages/core/admin/admin/src/pages/SettingsPage/constants.js @@ -2,67 +2,67 @@ import * as React from 'react'; export const SETTINGS_ROUTES_CE = [ { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "admin-roles-list" */ './pages/Roles/ProtectedListPage') ), path: '/settings/roles', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage') ), path: '/settings/roles/duplicate/:id', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage') ), path: '/settings/roles/new', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/ProtectedEditPage') ), path: '/settings/roles/:id', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "admin-users" */ './pages/Users/ProtectedListPage') ), path: '/settings/users', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "admin-edit-users" */ './pages/Users/ProtectedEditPage') ), path: '/settings/users/:id', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedCreateView') ), path: '/settings/webhooks/create', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedEditView') ), path: '/settings/webhooks/:id', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "webhook-list-page" */ './pages/Webhooks/ProtectedListView') ), path: '/settings/webhooks', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "api-tokens-list-page" */ './pages/ApiTokens/ProtectedListView') ), path: '/settings/api-tokens', }, { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "api-tokens-create-page" */ './pages/ApiTokens/ProtectedCreateView' ) @@ -70,13 +70,13 @@ export const SETTINGS_ROUTES_CE = [ path: '/settings/api-tokens/create', }, { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "api-tokens-edit-page" */ './pages/ApiTokens/ProtectedEditView') ), path: '/settings/api-tokens/:id', }, { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "transfer-tokens-create-page" */ './pages/TransferTokens/ProtectedCreateView' ) @@ -84,7 +84,7 @@ export const SETTINGS_ROUTES_CE = [ path: '/settings/transfer-tokens/create', }, { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "transfer-tokens-list-page" */ './pages/TransferTokens/ProtectedListView' ) @@ -92,7 +92,7 @@ export const SETTINGS_ROUTES_CE = [ path: '/settings/transfer-tokens', }, { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "transfer-tokens-edit-page" */ './pages/TransferTokens/ProtectedEditView' ) diff --git a/packages/core/admin/admin/src/pages/SettingsPage/index.js b/packages/core/admin/admin/src/pages/SettingsPage/index.js index 428260f2b2..d502b7152e 100644 --- a/packages/core/admin/admin/src/pages/SettingsPage/index.js +++ b/packages/core/admin/admin/src/pages/SettingsPage/index.js @@ -8,6 +8,7 @@ import { Redirect, Route, Switch, useParams } from 'react-router-dom'; import { useSettingsMenu } from '../../hooks'; import { useEnterprise } from '../../hooks/useEnterprise'; +import { createRoute } from '../../utils/createRoute'; import SettingsNav from './components/SettingsNav'; import { SETTINGS_ROUTES_CE } from './constants'; @@ -30,6 +31,26 @@ export function SettingsPage() { } ); + /** + * `Component` is an async function, which is passed as property of the + * addSettingsLink() API during the plugin bootstrap step. + * + * Because of that we can't just render , + * but have to await the function. + * + * This isn't a good React pattern and should be reconsidered. + */ + + const pluginSettingsRoutes = Object.values(settings).flatMap((section) => + section.links.map((link) => createRoute(link.Component, link.to, link.exact || false)) + ); + + // Since the useSettingsMenu hook can make API calls in order to check the links permissions + // We need to add a loading state to prevent redirecting the user while permissions are being checked + if (isLoading) { + return ; + } + if (!settingId) { return ; } @@ -43,49 +64,15 @@ export function SettingsPage() { })} /> - {isLoading ? ( - - ) : ( - - ( - }> - - - )} - exact - /> + + - {routes.map(({ path, Component }) => ( - ( - }> - - - )} - exact - /> - ))} + {routes.map(({ path, component }) => ( + + ))} - {Object.values(settings).flatMap((section) => - section.links.map(({ Component, to, exact }) => ( - ( - }> - - - )} - key={to} - path={to} - exact={exact || false} - /> - )) - )} - - )} + {pluginSettingsRoutes} + ); } diff --git a/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js b/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js index b8ac35a952..d863c007df 100644 --- a/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +++ b/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js @@ -9,11 +9,11 @@ import { HeaderLayout, Layout, Link, + Loader, Main, Typography, } from '@strapi/design-system'; import { - LoadingIndicatorPage, prefixFileUrlWithBackendUrl, SettingsPageTitle, useAPIErrorHandler, @@ -161,7 +161,12 @@ const ApplicationInfosPage = () => {
{isLoading ? ( - + + {formatMessage({ + id: 'Settings.application.isLoading', + defaultMessage: 'Loading', + })} + ) : (
{ afterAll(() => server.close()); it('should not display link upgrade version if not necessary', async () => { - const { queryByText, getByTestId } = setup(); + const { queryByText } = setup(); - await waitForElementToBeRemoved(() => getByTestId('loader')); + await waitForElementToBeRemoved(() => queryByText('Loading')); expect(queryByText('Upgrade your admin panel')).not.toBeInTheDocument(); }); @@ -127,18 +127,18 @@ describe('Application page', () => { strapiVersion: '4.0.0', }); - const { getByText, getByTestId } = setup(); + const { getByText, queryByText } = setup(); - await waitForElementToBeRemoved(() => getByTestId('loader')); + await waitForElementToBeRemoved(() => queryByText('Loading')); expect(getByText('v4.0.0')).toBeInTheDocument(); expect(getByText('Upgrade your admin panel')).toBeInTheDocument(); }); it('should render logo input if read permissions', async () => { - const { queryByText, getByTestId } = setup(); + const { queryByText } = setup(); - await waitForElementToBeRemoved(() => getByTestId('loader')); + await waitForElementToBeRemoved(() => queryByText('Loading')); expect(queryByText('Menu logo')).toBeInTheDocument(); }); @@ -153,9 +153,9 @@ describe('Application page', () => { }); it('should render save button if update permissions', async () => { - const { queryByText, getByTestId } = setup(); + const { queryByText } = setup(); - await waitForElementToBeRemoved(() => getByTestId('loader')); + await waitForElementToBeRemoved(() => queryByText('Loading')); expect(queryByText('Save')).toBeInTheDocument(); }); @@ -163,9 +163,9 @@ describe('Application page', () => { it('should not render save button if no update permissions', async () => { useRBAC.mockReturnValue({ allowedActions: { canRead: true, canUpdate: false } }); - const { queryByText, getByTestId } = setup(); + const { queryByText } = setup(); - await waitForElementToBeRemoved(() => getByTestId('loader')); + await waitForElementToBeRemoved(() => queryByText('Loading')); expect(queryByText('Save')).not.toBeInTheDocument(); }); @@ -173,9 +173,9 @@ describe('Application page', () => { it('should update project settings on save', async () => { useRBAC.mockReturnValue({ allowedActions: { canRead: true, canUpdate: true } }); - const { getByRole, getByTestId } = setup(); + const { getByRole, queryByText } = setup(); - await waitForElementToBeRemoved(() => getByTestId('loader')); + await waitForElementToBeRemoved(() => queryByText('Loading')); fireEvent.click(getByRole('button', { name: 'Save' })); diff --git a/packages/core/admin/admin/src/pages/SettingsPage/tests/index.test.js b/packages/core/admin/admin/src/pages/SettingsPage/tests/index.test.js index 4509147c41..90cdeff3dd 100644 --- a/packages/core/admin/admin/src/pages/SettingsPage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/SettingsPage/tests/index.test.js @@ -256,9 +256,7 @@ describe('ADMIN | pages | SettingsPage', () => { isDisplayed: true, permissions: [], to: '/settings/internationalization', - Component() { - return
i18n settings
; - }, + Component: () => ({ default: () =>
i18n settings
}), }, ], }, @@ -272,9 +270,7 @@ describe('ADMIN | pages | SettingsPage', () => { isDisplayed: true, permissions: [], to: '/settings/email-settings', - Component() { - return
i18n settings
; - }, + Component: () => ({ default: () =>
email settings
}), }, ], }, @@ -296,9 +292,7 @@ describe('ADMIN | pages | SettingsPage', () => { isDisplayed: true, permissions: [], to: '/settings/internationalization', - Component() { - return
i18n settings
; - }, + Component: () => ({ default: () =>
i18n settings
}), }, ], }, @@ -312,9 +306,7 @@ describe('ADMIN | pages | SettingsPage', () => { isDisplayed: true, permissions: [], to: '/settings/email-settings', - Component() { - return
email settings
; - }, + Component: () => ({ default: () =>
email settings
}), }, ], }, diff --git a/packages/core/admin/admin/src/tests/StrapiApp.test.js b/packages/core/admin/admin/src/tests/StrapiApp.test.js index 087ef244ba..e11d67efd8 100644 --- a/packages/core/admin/admin/src/tests/StrapiApp.test.js +++ b/packages/core/admin/admin/src/tests/StrapiApp.test.js @@ -135,7 +135,7 @@ describe('ADMIN | StrapiApp', () => { app.createSettingSection(section, links); expect(app.settings.foo).toBeDefined(); - expect(app.settings.foo.links).toEqual(expect.any(Object)); + expect(app.settings.foo.links).toEqual(links); }); it('should add a link correctly to the global section', () => { @@ -150,7 +150,7 @@ describe('ADMIN | StrapiApp', () => { app.addSettingsLink('global', link); expect(app.settings.global.links).toHaveLength(1); - expect(app.settings.global.links[0]).toEqual(expect.any(Object)); + expect(app.settings.global.links[0]).toEqual(link); }); it('should add an array of links correctly to the global section', () => { @@ -167,7 +167,7 @@ describe('ADMIN | StrapiApp', () => { app.addSettingsLinks('global', links); expect(app.settings.global.links).toHaveLength(1); - expect(app.settings.global.links).toEqual(expect.any(Object)); + expect(app.settings.global.links).toEqual(links); }); }); @@ -391,7 +391,7 @@ describe('ADMIN | StrapiApp', () => { app.addMenuLink(link); expect(app.menu[0]).toBeDefined(); - expect(app.menu[0]).toEqual(expect.any(Object)); + expect(app.menu[0]).toEqual(link); }); it('addCorePluginMenuLink should add a link to the menu', () => { diff --git a/packages/core/admin/admin/src/utils/createRoute.js b/packages/core/admin/admin/src/utils/createRoute.js new file mode 100644 index 0000000000..bfca09996a --- /dev/null +++ b/packages/core/admin/admin/src/utils/createRoute.js @@ -0,0 +1,45 @@ +import React, { useEffect, useState } from 'react'; + +import { LoadingIndicatorPage } from '@strapi/helper-plugin'; +import PropTypes from 'prop-types'; +import { Route } from 'react-router-dom'; + +const LazyCompo = ({ loadComponent }) => { + const [Compo, setCompo] = useState(null); + + useEffect(() => { + const loadCompo = async () => { + try { + const loadedCompo = await loadComponent(); + + setCompo(() => loadedCompo.default); + } catch (err) { + // TODO return the error component + console.log(err); + } + }; + + loadCompo(); + }, [loadComponent]); + + if (Compo) { + return ; + } + + return ; +}; + +LazyCompo.propTypes = { + loadComponent: PropTypes.func.isRequired, +}; + +export const createRoute = (Component, to, exact) => { + return ( + } + key={to} + path={to} + exact={exact || false} + /> + ); +}; diff --git a/packages/core/admin/admin/src/utils/tests/createRoute.test.js b/packages/core/admin/admin/src/utils/tests/createRoute.test.js new file mode 100644 index 0000000000..3ddfa5cf3e --- /dev/null +++ b/packages/core/admin/admin/src/utils/tests/createRoute.test.js @@ -0,0 +1,16 @@ +import { createRoute } from '../createRoute'; + +describe('ADMIN | CONTAINER | SettingsPage | utils | createRoute', () => { + it('should return a with the correctProps', () => { + const compo = () => 'test'; + + const { + props: { path, exact }, + key, + } = createRoute(compo, '/test', true); + + expect(key).toEqual('/test'); + expect(exact).toBeTruthy(); + expect(path).toEqual('/test'); + }); +}); diff --git a/packages/core/admin/ee/admin/pages/SettingsPage/constants.js b/packages/core/admin/ee/admin/pages/SettingsPage/constants.js index f6e04a62cc..53cc2148ec 100644 --- a/packages/core/admin/ee/admin/pages/SettingsPage/constants.js +++ b/packages/core/admin/ee/admin/pages/SettingsPage/constants.js @@ -4,7 +4,7 @@ export const SETTINGS_ROUTES_EE = [ ...(window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS) ? [ { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "audit-logs-settings-page" */ './pages/AuditLogs/ProtectedListPage' ) @@ -17,7 +17,7 @@ export const SETTINGS_ROUTES_EE = [ ...(window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS) ? [ { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "review-workflows-settings-list-view" */ './pages/ReviewWorkflows/pages/ListView' ) @@ -26,7 +26,7 @@ export const SETTINGS_ROUTES_EE = [ }, { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "review-workflows-settings-create-view" */ './pages/ReviewWorkflows/pages/CreateView' ) @@ -35,7 +35,7 @@ export const SETTINGS_ROUTES_EE = [ }, { - Component: React.lazy(() => + component: React.lazy(() => import( /* webpackChunkName: "review-workflows-settings-edit-view" */ './pages/ReviewWorkflows/pages/EditView' ) @@ -48,7 +48,7 @@ export const SETTINGS_ROUTES_EE = [ ...(window.strapi.features.isEnabled(window.strapi.features.SSO) ? [ { - Component: React.lazy(() => + component: React.lazy(() => import(/* webpackChunkName: "sso-settings-page" */ './pages/SingleSignOn') ), path: '/settings/single-sign-on', diff --git a/packages/core/content-type-builder/admin/src/index.js b/packages/core/content-type-builder/admin/src/index.js index c065d68db8..d48bc5f56d 100644 --- a/packages/core/content-type-builder/admin/src/index.js +++ b/packages/core/content-type-builder/admin/src/index.js @@ -22,7 +22,13 @@ export default { defaultMessage: 'Content Types Builder', }, permissions: PERMISSIONS.main, - Component: () => import(/* webpackChunkName: "content-type-builder" */ './pages/App'), + async Component() { + const component = await import( + /* webpackChunkName: "content-type-builder" */ './pages/App' + ); + + return component; + }, }); app.registerPlugin({ diff --git a/packages/core/email/admin/src/index.js b/packages/core/email/admin/src/index.js index 7569a47fac..f861c89c73 100644 --- a/packages/core/email/admin/src/index.js +++ b/packages/core/email/admin/src/index.js @@ -1,3 +1,10 @@ +// NOTE TO PLUGINS DEVELOPERS: +// If you modify this file by adding new options to the plugin entry point +// Here's the file: strapi/docs/3.x/plugin-development/frontend-field-api.md +// Here's the file: strapi/docs/3.x/guides/registering-a-field-in-admin.md +// Also the strapi-generate-plugins/files/admin/src/index.js needs to be updated +// IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED + import { prefixPluginTranslations } from '@strapi/helper-plugin'; import { PERMISSIONS } from './constants'; @@ -18,12 +25,17 @@ export default { }, id: 'settings', to: `/settings/email`, - Component: () => import(/* webpackChunkName: "email-settings-page" */ './pages/Settings'), + async Component() { + const component = await import( + /* webpackChunkName: "email-settings-page" */ './pages/Settings' + ); + + return component; + }, permissions: PERMISSIONS.settings, }, ] ); - app.registerPlugin({ id: 'email', name: 'email', diff --git a/packages/core/helper-plugin/src/features/StrapiApp.jsx b/packages/core/helper-plugin/src/features/StrapiApp.jsx index 36e11a0ba1..092f84d19e 100644 --- a/packages/core/helper-plugin/src/features/StrapiApp.jsx +++ b/packages/core/helper-plugin/src/features/StrapiApp.jsx @@ -83,8 +83,7 @@ StrapiAppProvider.propTypes = { defaultMessage: PropTypes.string.isRequired, }).isRequired, permissions: PropTypes.array, - // React.lazy loadable - Component: PropTypes.object, + Component: PropTypes.func, }) ).isRequired, plugins: PropTypes.object.isRequired, diff --git a/packages/core/helper-plugin/src/index.js b/packages/core/helper-plugin/src/index.js index 847b5c8e2b..0141cdc69d 100644 --- a/packages/core/helper-plugin/src/index.js +++ b/packages/core/helper-plugin/src/index.js @@ -108,4 +108,3 @@ export { setHexOpacity } from './utils/setHexOpacity'; export * from './utils/stopPropagation'; export { translatedErrors } from './utils/translatedErrors'; export { wrapAxiosInstance } from './utils/wrapAxiosInstance'; -export * from './utils/once'; diff --git a/packages/core/upload/admin/src/index.js b/packages/core/upload/admin/src/index.js index abf97a88ab..5c54a2b8ff 100644 --- a/packages/core/upload/admin/src/index.js +++ b/packages/core/upload/admin/src/index.js @@ -1,3 +1,9 @@ +// NOTE TO PLUGINS DEVELOPERS: +// If you modify this file by adding new options to the plugin entry point +// Here's the file: strapi/docs/3.0.0-beta.x/plugin-development/frontend-field-api.md +// Here's the file: strapi/docs/3.0.0-beta.x/guides/registering-a-field-in-admin.md +// Also the strapi-generate-plugins/files/admin/src/index.js needs to be updated +// IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED import { prefixPluginTranslations } from '@strapi/helper-plugin'; import pluginPkg from '../../package.json'; @@ -21,7 +27,11 @@ export default { defaultMessage: 'Media Library', }, permissions: PERMISSIONS.main, - Component: () => import(/* webpackChunkName: "upload" */ './pages/App'), + async Component() { + const component = await import(/* webpackChunkName: "upload" */ './pages/App'); + + return component; + }, }); app.addFields({ type: 'media', Component: MediaLibraryInput }); @@ -40,7 +50,13 @@ export default { defaultMessage: 'Media Library', }, to: '/settings/media-library', - Component: () => import(/* webpackChunkName: "upload-settings" */ './pages/SettingsPage'), + async Component() { + const component = await import( + /* webpackChunkName: "upload-settings" */ './pages/SettingsPage' + ); + + return component; + }, permissions: PERMISSIONS.settings, }); }, diff --git a/packages/plugins/documentation/admin/src/index.js b/packages/plugins/documentation/admin/src/index.js index 2c407f8ac7..a2b56dd336 100644 --- a/packages/plugins/documentation/admin/src/index.js +++ b/packages/plugins/documentation/admin/src/index.js @@ -24,7 +24,13 @@ export default { defaultMessage: 'Documentation', }, permissions: PERMISSIONS.main, - Component: () => import(/* webpackChunkName: "documentation-page" */ './pages/PluginPage'), + async Component() { + const component = await import( + /* webpackChunkName: "documentation-page" */ './pages/PluginPage' + ); + + return component; + }, }); app.registerPlugin({ @@ -40,8 +46,13 @@ export default { }, id: 'documentation', to: `/settings/${pluginId}`, - Component: () => - import(/* webpackChunkName: "documentation-settings" */ './pages/SettingsPage'), + async Component() { + const component = await import( + /* webpackChunkName: "documentation-settings" */ './pages/SettingsPage' + ); + + return component; + }, permissions: PERMISSIONS.main, }); }, diff --git a/packages/plugins/i18n/admin/src/index.js b/packages/plugins/i18n/admin/src/index.js index 68b6b8686a..85173e0e94 100644 --- a/packages/plugins/i18n/admin/src/index.js +++ b/packages/plugins/i18n/admin/src/index.js @@ -61,7 +61,13 @@ export default { id: 'internationalization', to: '/settings/internationalization', - Component: () => import(/* webpackChunkName: "i18n-settings-page" */ './pages/SettingsPage'), + async Component() { + const component = await import( + /* webpackChunkName: "i18n-settings-page" */ './pages/SettingsPage' + ); + + return component; + }, permissions: PERMISSIONS.accessMain, }); diff --git a/packages/plugins/users-permissions/admin/src/index.js b/packages/plugins/users-permissions/admin/src/index.js index 7f8992dd24..58dd5c556a 100644 --- a/packages/plugins/users-permissions/admin/src/index.js +++ b/packages/plugins/users-permissions/admin/src/index.js @@ -32,8 +32,13 @@ export default { }, id: 'roles', to: `/settings/users-permissions/roles`, - Component: () => - import(/* webpackChunkName: "users-roles-settings-page" */ './pages/Roles'), + async Component() { + const component = await import( + /* webpackChunkName: "users-roles-settings-page" */ './pages/Roles' + ); + + return component; + }, permissions: PERMISSIONS.accessRoles, }, { @@ -43,8 +48,13 @@ export default { }, id: 'providers', to: `/settings/users-permissions/providers`, - Component: () => - import(/* webpackChunkName: "users-providers-settings-page" */ './pages/Providers'), + async Component() { + const component = await import( + /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers' + ); + + return component; + }, permissions: PERMISSIONS.readProviders, }, { @@ -54,8 +64,13 @@ export default { }, id: 'email-templates', to: `/settings/users-permissions/email-templates`, - Component: () => - import(/* webpackChunkName: "users-email-settings-page" */ './pages/EmailTemplates'), + async Component() { + const component = await import( + /* webpackChunkName: "users-email-settings-page" */ './pages/EmailTemplates' + ); + + return component; + }, permissions: PERMISSIONS.readEmailTemplates, }, { @@ -65,10 +80,13 @@ export default { }, id: 'advanced-settings', to: `/settings/users-permissions/advanced-settings`, - Component: () => - import( + async Component() { + const component = await import( /* webpackChunkName: "users-advanced-settings-page" */ './pages/AdvancedSettings' - ), + ); + + return component; + }, permissions: PERMISSIONS.readAdvancedSettings, }, ]