From 2250ecb192006ce85b2bf1dc3aec50c8faeccaf0 Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Mon, 14 Nov 2022 10:56:57 +0100 Subject: [PATCH 1/7] Create hook to lazy load custom field components --- .../components/Inputs/index.js | 24 +- .../hooks/useLazyComponents/index.js | 44 ++++ .../content-manager/pages/EditView/index.js | 216 ++++++++++-------- 3 files changed, 170 insertions(+), 114 deletions(-) create mode 100644 packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/index.js diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/index.js b/packages/core/admin/admin/src/content-manager/components/Inputs/index.js index 85a6b04d24..2e55e1750c 100644 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/index.js +++ b/packages/core/admin/admin/src/content-manager/components/Inputs/index.js @@ -5,7 +5,7 @@ import get from 'lodash/get'; import omit from 'lodash/omit'; import take from 'lodash/take'; import isEqual from 'react-fast-compare'; -import { GenericInput, NotAllowedInput, useLibrary, useCustomFields } from '@strapi/helper-plugin'; +import { GenericInput, NotAllowedInput, useLibrary } from '@strapi/helper-plugin'; import { useContentTypeLayout } from '../../hooks'; import { getFieldName } from '../../utils'; import Wysiwyg from '../Wysiwyg'; @@ -37,11 +37,11 @@ function Inputs({ queryInfos, value, size, + customFieldInputs, }) { const { fields } = useLibrary(); const { formatMessage } = useIntl(); const { contentType: currentContentTypeLayout } = useContentTypeLayout(); - const customFieldsRegistry = useCustomFields(); const disabled = useMemo(() => !get(metadatas, 'editable', true), [metadatas]); const { type, customField: customFieldUid } = fieldSchema; @@ -194,19 +194,6 @@ function Inputs({ return minutes % metadatas.step === 0 ? metadatas.step : step; }, [inputType, inputValue, metadatas.step, step]); - // Memoize the component to avoid remounting it and losing state - const CustomFieldInput = useMemo(() => { - if (customFieldUid) { - const customField = customFieldsRegistry.get(customFieldUid); - const CustomFieldInput = React.lazy(customField.components.Input); - - return CustomFieldInput; - } - - // Not a custom field, component won't be used - return null; - }, [customFieldUid, customFieldsRegistry]); - if (visible === false) { return null; } @@ -268,12 +255,9 @@ function Inputs({ media: fields.media, wysiwyg: Wysiwyg, ...fields, + ...customFieldInputs, }; - if (customFieldUid) { - customInputs[customFieldUid] = CustomFieldInput; - } - return ( } componentUids - The uids to look up components + * @returns object + */ +const useLazyComponents = (componentUids) => { + const [lazyComponentStore, setLazyComponentStore] = useState({}); + const [loading, setLoading] = useState(true); + const customFieldsRegistry = useCustomFields(); + + useEffect(() => { + const lazyLoadComponents = async (uids, components) => { + const modules = await Promise.all(components); + + uids.forEach((uid, index) => { + if (!Object.keys(lazyComponentStore).includes(uid)) { + setLazyComponentStore({ ...lazyComponentStore, [uid]: modules[index].default }); + } + }); + }; + + if (componentUids.length) { + const componentPromises = componentUids.map((uid) => { + const customField = customFieldsRegistry.get(uid); + + return customField.components.Input(); + }); + + lazyLoadComponents(componentUids, componentPromises); + } + + if (componentUids.length === Object.keys(lazyComponentStore).length) { + setLoading(false); + } + }, [componentUids, customFieldsRegistry, loading, lazyComponentStore]); + + return { isLazyLoading: loading, lazyComponentStore }; +}; + +export default useLazyComponents; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js index 0ed1f16a0e..1f611d5b16 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js @@ -1,11 +1,11 @@ -import React, { Suspense, memo, useCallback, useMemo } from 'react'; +import React, { memo, useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; import get from 'lodash/get'; import { CheckPermissions, - LoadingIndicatorPage, useTracking, LinkButton, + LoadingIndicatorPage, } from '@strapi/helper-plugin'; import { useIntl } from 'react-intl'; import { ContentLayout } from '@strapi/design-system/Layout'; @@ -29,10 +29,29 @@ import Informations from './Informations'; import Header from './Header'; import { createAttributesLayout, getFieldsActionMatchingPermissions } from './utils'; import DeleteLink from './DeleteLink'; +import useLazyComponents from '../../hooks/useLazyComponents'; const cmPermissions = permissions.contentManager; const ctbPermissions = [{ action: 'plugin::content-type-builder.read', subject: null }]; +const getCustomFieldUidsFromLayout = (layout) => { + // Get all the fields on the content-type and its components + const allFields = [ + ...layout.contentType.layouts.edit, + ...Object.values(layout.components).flatMap((component) => component.layouts.edit), + ].flat(); + // Filter that down to custom fields and map the uids + const customFieldUids = allFields + .filter((field) => field.fieldSchema.customField) + .map((customField) => customField.fieldSchema.customField); + // Make sure the list is unique + const uniqueCustomFieldUids = customFieldUids.filter( + (uid, index) => customFieldUids.indexOf(uid) === index + ); + + return uniqueCustomFieldUids; +}; + /* eslint-disable react/no-array-index-key */ const EditView = ({ allowedActions, @@ -46,6 +65,10 @@ const EditView = ({ }) => { const { trackUsage } = useTracking(); const { formatMessage } = useIntl(); + + const customFieldUids = getCustomFieldUidsFromLayout(layout); + const { isLazyLoading, lazyComponentStore } = useLazyComponents(customFieldUids); + const { createActionAllowedFields, readActionAllowedFields, updateActionAllowedFields } = useMemo(() => { return getFieldsActionMatchingPermissions(userPermissions, slug); @@ -86,6 +109,10 @@ const EditView = ({ ); }, [currentContentTypeLayoutData]); + if (isLazyLoading) { + return ; + } + return ( {({ @@ -132,110 +159,109 @@ const EditView = ({ - }> - - {formattedContentTypeLayout.map((row, index) => { - if (isDynamicZone(row)) { - const { - 0: { - 0: { name, fieldSchema, metadatas, labelAction }, - }, - } = row; - - return ( - - - - - - - - ); - } + + {formattedContentTypeLayout.map((row, index) => { + if (isDynamicZone(row)) { + const { + 0: { + 0: { name, fieldSchema, metadatas, labelAction }, + }, + } = row; return ( - - - {row.map((grid, gridIndex) => { - return ( - - {grid.map( - ({ - fieldSchema, - labelAction, - metadatas, - name, - size, - queryInfos, - }) => { - const isComponent = fieldSchema.type === 'component'; + + + + + + + + ); + } - if (isComponent) { - const { - component, - max, - min, - repeatable = false, - required = false, - } = fieldSchema; + return ( + + + {row.map((grid, gridIndex) => { + return ( + + {grid.map( + ({ + fieldSchema, + labelAction, + metadatas, + name, + size, + queryInfos, + }) => { + const isComponent = fieldSchema.type === 'component'; - return ( - - - - ); - } + if (isComponent) { + const { + component, + max, + min, + repeatable = false, + required = false, + } = fieldSchema; return ( - - + ); } - )} - - ); - })} - - - ); - })} - - + + return ( + + + + ); + } + )} + + ); + })} + + + ); + })} + From 6cef5fd6a97575a988a560c861c462f063567f52 Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Tue, 15 Nov 2022 18:30:44 +0100 Subject: [PATCH 2/7] Move function to utils --- .../content-manager/pages/EditView/index.js | 24 ++++--------------- .../utils/getCustomFieldUidsFromLayout.js | 19 +++++++++++++++ .../pages/EditView/utils/index.js | 1 + 3 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js index 1f611d5b16..aee839f6b1 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js @@ -27,31 +27,17 @@ import { getTrad } from '../../utils'; import DraftAndPublishBadge from './DraftAndPublishBadge'; import Informations from './Informations'; import Header from './Header'; -import { createAttributesLayout, getFieldsActionMatchingPermissions } from './utils'; +import { + createAttributesLayout, + getFieldsActionMatchingPermissions, + getCustomFieldUidsFromLayout, +} from './utils'; import DeleteLink from './DeleteLink'; import useLazyComponents from '../../hooks/useLazyComponents'; const cmPermissions = permissions.contentManager; const ctbPermissions = [{ action: 'plugin::content-type-builder.read', subject: null }]; -const getCustomFieldUidsFromLayout = (layout) => { - // Get all the fields on the content-type and its components - const allFields = [ - ...layout.contentType.layouts.edit, - ...Object.values(layout.components).flatMap((component) => component.layouts.edit), - ].flat(); - // Filter that down to custom fields and map the uids - const customFieldUids = allFields - .filter((field) => field.fieldSchema.customField) - .map((customField) => customField.fieldSchema.customField); - // Make sure the list is unique - const uniqueCustomFieldUids = customFieldUids.filter( - (uid, index) => customFieldUids.indexOf(uid) === index - ); - - return uniqueCustomFieldUids; -}; - /* eslint-disable react/no-array-index-key */ const EditView = ({ allowedActions, diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js new file mode 100644 index 0000000000..333398fdd9 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js @@ -0,0 +1,19 @@ +const getCustomFieldUidsFromLayout = (layout) => { + // Get all the fields on the content-type and its components + const allFields = [ + ...layout.contentType.layouts.edit, + ...Object.values(layout.components).flatMap((component) => component.layouts.edit), + ].flat(); + // Filter that down to custom fields and map the uids + const customFieldUids = allFields + .filter((field) => field.fieldSchema.customField) + .map((customField) => customField.fieldSchema.customField); + // Make sure the list is unique + const uniqueCustomFieldUids = customFieldUids.filter( + (uid, index) => customFieldUids.indexOf(uid) === index + ); + + return uniqueCustomFieldUids; +}; + +export default getCustomFieldUidsFromLayout; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/index.js b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/index.js index 4412abb24d..c408b5b3a4 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/index.js @@ -1,3 +1,4 @@ // eslint-disable-next-line import/prefer-default-export export { default as createAttributesLayout } from './createAttributesLayout'; export { default as getFieldsActionMatchingPermissions } from './getFieldsActionMatchingPermissions'; +export { default as getCustomFieldUidsFromLayout } from './getCustomFieldUidsFromLayout'; From 7db54acd8df2bee3851c8cf21ac3d8c3712c0ae5 Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Wed, 16 Nov 2022 10:16:11 +0100 Subject: [PATCH 3/7] Test getCustomFieldUidsFromLayout --- .../getCustomFieldUidsFromLayout.test.js | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/getCustomFieldUidsFromLayout.test.js diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/getCustomFieldUidsFromLayout.test.js b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/getCustomFieldUidsFromLayout.test.js new file mode 100644 index 0000000000..a6625d6007 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/getCustomFieldUidsFromLayout.test.js @@ -0,0 +1,86 @@ +import getCustomFieldUidsFromLayout from '../getCustomFieldUidsFromLayout'; + +describe('CONTENT MANAGER | CONTAINERS | EditView | utils | getCustomFieldUidsFromLayout', () => { + it('gets a unique list of custom field uids on the content-type layout', () => { + const mockLayoutData = { + contentType: { + layouts: { + edit: [ + [ + { + name: 'short_text', + size: 6, + fieldSchema: { + type: 'string', + }, + }, + ], + [ + { + name: 'dynamiczone', + size: 12, + fieldSchema: { + type: 'dynamiczone', + components: ['basic.simple'], + }, + }, + ], + [ + { + name: 'custom_field_2', + size: 6, + fieldSchema: { + type: 'string', + customField: 'plugin::color-picker.color', + }, + }, + ], + [ + { + name: 'custom_field_2', + size: 6, + fieldSchema: { + type: 'string', + customField: 'plugin::color-picker.color', + }, + }, + ], + ], + }, + }, + components: { + 'basic.simple': { + uid: 'basic.simple', + layouts: { + edit: [ + [ + { + name: 'name', + size: 6, + fieldSchema: { + type: 'string', + required: true, + }, + }, + ], + [ + { + name: 'custom_field_3', + size: 6, + fieldSchema: { + type: 'string', + customField: 'plugin::test-plugin.test', + }, + }, + ], + ], + }, + }, + }, + }; + + const expected = ['plugin::color-picker.color', 'plugin::test-plugin.test']; + + expect(getCustomFieldUidsFromLayout(mockLayoutData)).toEqual(expected); + }); +}); From 55a420d35d5bb7ca71a64ea667855ae7aac35e74 Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Wed, 16 Nov 2022 13:57:21 +0100 Subject: [PATCH 4/7] Test useLazyComponents --- .../tests/useLazyComponents.test.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js diff --git a/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js b/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js new file mode 100644 index 0000000000..e5effa9a15 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js @@ -0,0 +1,50 @@ +import { renderHook } from '@testing-library/react-hooks'; +import useLazyComponents from '../index'; + +const mockCustomField = { + name: 'color', + pluginId: 'mycustomfields', + type: 'text', + icon: jest.fn(), + intlLabel: { + id: 'mycustomfields.color.label', + defaultMessage: 'Color', + }, + intlDescription: { + id: 'mycustomfields.color.description', + defaultMessage: 'Select any color', + }, + components: { + Input: jest.fn().mockResolvedValue({ default: jest.fn() }), + }, +}; + +jest.mock('@strapi/helper-plugin', () => ({ + useCustomFields: () => ({ + get: jest.fn().mockReturnValue(mockCustomField), + }), +})); + +describe('useLazyComponents', () => { + it('lazy loads the components', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useLazyComponents(['plugin::test.test']) + ); + + expect(result.current).toEqual({ isLazyLoading: true, lazyComponentStore: {} }); + + await waitForNextUpdate(); + + expect(JSON.stringify(result.current)).toEqual( + JSON.stringify({ + isLazyLoading: false, + lazyComponentStore: { 'plugin::test.test': jest.fn() }, + }) + ); + }); + it('handles no components to load', async () => { + const { result } = renderHook(() => useLazyComponents([])); + + expect(result.current).toEqual({ isLazyLoading: false, lazyComponentStore: {} }); + }); +}); From ba6361a2664fe6ed09ba0107be6aef707dd6a98d Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Mon, 21 Nov 2022 11:11:42 +0100 Subject: [PATCH 5/7] Fix ErrorBoundary fallback component --- .../components/ErrorFallback.js | 13 +++++++++++++ .../pages/CollectionTypeRecursivePath/index.js | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.js diff --git a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.js b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.js new file mode 100644 index 0000000000..9f2af196ba --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { AnErrorOccurred } from '@strapi/helper-plugin'; +import { Box } from '@strapi/design-system/Box'; + +const ErrorFallback = () => { + return ( + + + + ); +}; + +export default ErrorFallback; diff --git a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js index 0fbed8d7fb..a8fa323c24 100644 --- a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js @@ -3,7 +3,7 @@ import { Switch, Route } from 'react-router-dom'; import { ErrorBoundary } from 'react-error-boundary'; import { get } from 'lodash'; import PropTypes from 'prop-types'; -import { ErrorFallback, LoadingIndicatorPage, CheckPagePermissions } from '@strapi/helper-plugin'; +import { LoadingIndicatorPage, CheckPagePermissions } from '@strapi/helper-plugin'; import permissions from '../../../permissions'; import { ContentTypeLayoutContext } from '../../contexts'; import { useFetchContentTypeLayout } from '../../hooks'; @@ -12,6 +12,7 @@ import EditViewLayoutManager from '../EditViewLayoutManager'; import EditSettingsView from '../EditSettingsView'; import ListViewLayout from '../ListViewLayoutManager'; import ListSettingsView from '../ListSettingsView'; +import ErrorFallback from './components/ErrorFallback'; const cmPermissions = permissions.contentManager; From dfac1a9eddfd1e7433f4e8acc324ff09fa2cf22f Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Wed, 23 Nov 2022 10:21:58 +0100 Subject: [PATCH 6/7] Use Set instead of filter --- .../pages/EditView/utils/getCustomFieldUidsFromLayout.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js index 333398fdd9..bda7feb8a1 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js @@ -9,9 +9,7 @@ const getCustomFieldUidsFromLayout = (layout) => { .filter((field) => field.fieldSchema.customField) .map((customField) => customField.fieldSchema.customField); // Make sure the list is unique - const uniqueCustomFieldUids = customFieldUids.filter( - (uid, index) => customFieldUids.indexOf(uid) === index - ); + const uniqueCustomFieldUids = [...new Set(customFieldUids)]; return uniqueCustomFieldUids; }; From 0343495ea1cb8def84be108bb443fe4bf195a80c Mon Sep 17 00:00:00 2001 From: Mark Kaylor Date: Wed, 23 Nov 2022 21:40:53 +0100 Subject: [PATCH 7/7] Select custom field uids from layout using reselect --- .../admin/src/content-manager/pages/EditView/index.js | 8 ++++---- .../admin/src/content-manager/pages/EditView/selectors.js | 8 ++++++-- .../pages/EditView/utils/getCustomFieldUidsFromLayout.js | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js index f0823c80aa..a692cf0f5c 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js @@ -27,10 +27,10 @@ import useLazyComponents from '../../hooks/useLazyComponents'; import DraftAndPublishBadge from './DraftAndPublishBadge'; import Informations from './Informations'; import Header from './Header'; -import { getFieldsActionMatchingPermissions, getCustomFieldUidsFromLayout } from './utils'; +import { getFieldsActionMatchingPermissions } from './utils'; import DeleteLink from './DeleteLink'; import GridRow from './GridRow'; -import { selectCurrentLayout, selectAttributesLayout } from './selectors'; +import { selectCurrentLayout, selectAttributesLayout, selectCustomFieldUids } from './selectors'; const cmPermissions = permissions.contentManager; const ctbPermissions = [{ action: 'plugin::content-type-builder.read', subject: null }]; @@ -40,12 +40,12 @@ const EditView = ({ allowedActions, isSingleType, goBack, slug, id, origin, user const { trackUsage } = useTracking(); const { formatMessage } = useIntl(); - const { layout, formattedContentTypeLayout } = useSelector((state) => ({ + const { layout, formattedContentTypeLayout, customFieldUids } = useSelector((state) => ({ layout: selectCurrentLayout(state), formattedContentTypeLayout: selectAttributesLayout(state), + customFieldUids: selectCustomFieldUids(state), })); - const customFieldUids = getCustomFieldUidsFromLayout(layout); const { isLazyLoading, lazyComponentStore } = useLazyComponents(customFieldUids); const { createActionAllowedFields, readActionAllowedFields, updateActionAllowedFields } = diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/selectors.js b/packages/core/admin/admin/src/content-manager/pages/EditView/selectors.js index 90185c81d3..648c2c8dee 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/selectors.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/selectors.js @@ -1,5 +1,5 @@ import { createSelector } from 'reselect'; -import { createAttributesLayout } from './utils'; +import { createAttributesLayout, getCustomFieldUidsFromLayout } from './utils'; const selectCurrentLayout = (state) => state['content-manager_editViewLayoutManager'].currentLayout; @@ -7,4 +7,8 @@ const selectAttributesLayout = createSelector(selectCurrentLayout, (layout) => createAttributesLayout(layout?.contentType ?? {}) ); -export { selectCurrentLayout, selectAttributesLayout }; +const selectCustomFieldUids = createSelector(selectCurrentLayout, (layout) => + getCustomFieldUidsFromLayout(layout) +); + +export { selectCurrentLayout, selectAttributesLayout, selectCustomFieldUids }; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js index bda7feb8a1..b4fb1dffd1 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js @@ -1,4 +1,5 @@ const getCustomFieldUidsFromLayout = (layout) => { + if (!layout) return []; // Get all the fields on the content-type and its components const allFields = [ ...layout.contentType.layouts.edit,