diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/DataManagerProvider.tsx b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/DataManagerProvider.tsx index 6c3cd65f87..9efaca1762 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/DataManagerProvider.tsx +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/DataManagerProvider.tsx @@ -22,7 +22,6 @@ import { DataManagerContext } from '../../contexts/DataManagerContext'; import { useFormModalNavigation } from '../../hooks/useFormModalNavigation'; import { pluginId } from '../../pluginId'; import { getTrad } from '../../utils/getTrad'; -import { makeUnique } from '../../utils/makeUnique'; import { useAutoReloadOverlayBlocker } from '../AutoReloadOverlayBlocker'; import { FormModal } from '../FormModal/FormModal'; @@ -420,7 +419,7 @@ const DataManagerProvider = ({ children }: DataManagerProviderProps) => { const composWithCompos = retrieveComponentsThatHaveComponents(allCompos); - return makeUnique(composWithCompos); + return composWithCompos; }; const getAllNestedComponents = () => { diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.ts b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.ts index ce1337adc0..aa55f9af30 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.ts +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.ts @@ -1,12 +1,20 @@ import get from 'lodash/get'; -import { makeUnique } from '../../../utils/makeUnique'; - import type { Component, AttributeType, Components } from '../../../types'; +import type { Internal } from '@strapi/types'; + +type ChildComponent = { + component: Internal.UID.Component; +}; + +export type ComponentWithChildren = { + component: Internal.UID.Component; + childComponents: ChildComponent[]; +}; const retrieveComponentsThatHaveComponents = (allComponents: Components) => { const componentsThatHaveNestedComponents = Object.keys(allComponents).reduce( - (acc: any, current) => { + (acc: ComponentWithChildren[], current) => { const currentComponent = get(allComponents, [current]); const compoWithChildren = getComponentWithChildComponents(currentComponent); @@ -19,18 +27,24 @@ const retrieveComponentsThatHaveComponents = (allComponents: Components) => { [] ); - return makeUnique(componentsThatHaveNestedComponents); + return componentsThatHaveNestedComponents; }; -const getComponentWithChildComponents = (component: Component) => { +const getComponentWithChildComponents = (component: Component): ComponentWithChildren => { const attributes = get(component, ['schema', 'attributes'], []) as AttributeType[]; return { component: component.uid, - childComponents: attributes.filter((attribute) => { - const { type } = attribute; + childComponents: attributes + .filter((attribute) => { + const { type } = attribute; - return type === 'component'; - }), + return type === 'component'; + }) + .map((attribute) => { + return { + component: attribute.component, + } as ChildComponent; + }), }; }; diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveNestedComponents.ts b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveNestedComponents.ts index bc441a8124..0a4ea85947 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveNestedComponents.ts +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/retrieveNestedComponents.ts @@ -1,14 +1,19 @@ +import type { Components, AttributeType } from '../../../types'; import type { Internal } from '@strapi/types'; export type NestedComponent = { component: Internal.UID.Component; - parentCompoUid?: Internal.UID.Component[]; + uidsOfAllParents?: Internal.UID.Component[]; + parentCompoUid?: Internal.UID.Component; }; -export const retrieveNestedComponents = (appComponents: any): NestedComponent[] => { - const nestedComponents = Object.keys(appComponents).reduce((acc: any, current: any) => { +export const retrieveNestedComponents = (appComponents: Components): NestedComponent[] => { + const nestedComponents = Object.keys(appComponents).reduce((acc: NestedComponent[], current) => { const componentAttributes = appComponents?.[current]?.schema?.attributes ?? []; - const currentComponentNestedCompos = getComponentsFromComponent(componentAttributes, current); + const currentComponentNestedCompos = getComponentsFromComponent( + componentAttributes, + current as Internal.UID.Component + ); return [...acc, ...currentComponentNestedCompos]; }, []); @@ -16,10 +21,10 @@ export const retrieveNestedComponents = (appComponents: any): NestedComponent[] }; const getComponentsFromComponent = ( - componentAttributes: any, + componentAttributes: AttributeType[], parentCompoUid: Internal.UID.Component ) => { - return componentAttributes.reduce((acc: any, current: any) => { + return componentAttributes.reduce((acc: NestedComponent[], current) => { const { type, component } = current; if (type === 'component') { acc.push({ @@ -32,7 +37,7 @@ const getComponentsFromComponent = ( }, []); }; -// merge components different parents if they exist +// merge duplicate components const mergeComponents = (originalComponents: NestedComponent[]): NestedComponent[] => { const componentMap = new Map(); // Populate the map with component and its parents @@ -47,7 +52,7 @@ const mergeComponents = (originalComponents: NestedComponent[]): NestedComponent const transformedComponents: NestedComponent[] = Array.from(componentMap.entries()).map( ([component, parentCompoUidSet]) => ({ component, - parentCompoUid: Array.from(parentCompoUidSet), + uidsOfAllParents: Array.from(parentCompoUidSet), }) ); diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveComponentsThatHaveComponents.test.ts b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveComponentsThatHaveComponents.test.ts index 005be3bdee..6d979d23be 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveComponentsThatHaveComponents.test.ts +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveComponentsThatHaveComponents.test.ts @@ -85,12 +85,7 @@ describe('retrieveComponentsThatHaveComponents', () => { component: 'blog.slider', childComponents: [ { - name: 'slide', component: 'default.slide', - type: 'component', - repeatable: true, - min: 1, - max: 5, }, ], }); @@ -111,12 +106,7 @@ describe('retrieveComponentsThatHaveComponents', () => { component: 'blog.slider', childComponents: [ { - name: 'slide', component: 'default.slide', - type: 'component', - repeatable: true, - min: 1, - max: 5, }, ], }, diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveNestedComponents.test.ts b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveNestedComponents.test.ts index 5aba7dc1c4..45a7d04df8 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveNestedComponents.test.ts +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/utils/tests/retrieveNestedComponents.test.ts @@ -1,8 +1,10 @@ import { retrieveNestedComponents } from '../retrieveNestedComponents'; +import type { Components } from '../../../../types'; + describe('CONTENT TYPE BUILDER | COMPONENTS | DataManagerProvider | utils | retrieveNestedComponents', () => { it('should return an array of nested components', () => { - const components = { + const components: Components = { 'default.closingperiod': { uid: 'default.closingperiod', category: 'default', @@ -52,7 +54,7 @@ describe('CONTENT TYPE BUILDER | COMPONENTS | DataManagerProvider | utils | retr const expected = [ { component: 'default.dish', - parentCompoUid: ['default.closingperiod'], + uidsOfAllParents: ['default.closingperiod'], }, ]; @@ -60,7 +62,7 @@ describe('CONTENT TYPE BUILDER | COMPONENTS | DataManagerProvider | utils | retr }); it('should return both parents', () => { - const components = { + const components: Components = { 'default.closingperiod': { uid: 'default.closingperiod', category: 'default', @@ -123,7 +125,7 @@ describe('CONTENT TYPE BUILDER | COMPONENTS | DataManagerProvider | utils | retr const expected = [ { component: 'default.dish', - parentCompoUid: ['default.closingperiod', 'default.openingperiod'], + uidsOfAllParents: ['default.closingperiod', 'default.openingperiod'], }, ]; diff --git a/packages/core/content-type-builder/admin/src/utils/getMaxDepth.ts b/packages/core/content-type-builder/admin/src/utils/getMaxDepth.ts index f679e0cca2..72651735bb 100644 --- a/packages/core/content-type-builder/admin/src/utils/getMaxDepth.ts +++ b/packages/core/content-type-builder/admin/src/utils/getMaxDepth.ts @@ -22,8 +22,13 @@ const findComponent = ( }; /** - * gets the maximum depth child component - * for a specific component + * Recursively calculates the maximum depth of nested child components + * for a given component UID. + * + * @param componentUid - The UID of the component to start from. + * @param components - The array of all components with their child components. + * @param currentDepth - The current depth of the recursion. Defaults to 0. + * @returns The maximum depth of the nested child components. */ export const getChildrenMaxDepth = ( componentUid: Internal.UID.Component, @@ -31,13 +36,19 @@ export const getChildrenMaxDepth = ( currentDepth = 0 ) => { const component = findComponent(componentUid, components); + + // If the component doesn't exist or has no child components, return the current depth. if (!component || !component.childComponents || component.childComponents.length === 0) { return currentDepth; } let maxDepth = currentDepth; + + // Iterate through each child component to calculate their respective depths. component.childComponents.forEach((child) => { + // Recursively calculate the depth of the child component. const depth = getChildrenMaxDepth(child.component, components, currentDepth + 1); + // Update the maximum depth if the child's depth is greater. if (depth > maxDepth) { maxDepth = depth; } @@ -46,20 +57,37 @@ export const getChildrenMaxDepth = ( return maxDepth; }; -// get the current component depth +/** + * Calculates the depth of a component within a nested component tree. + * Depth is defined as the level at which the component is nested. + * For example, a component at Depth 3 is the third nested component. + * + * @param component - The UID of the component to find the depth for. + * @param components - The array of all nested components. + * @returns The depth level of the component within the nested tree. + */ export const getComponentDepth = ( component: Internal.UID.Schema, components: Array ) => { + /** + * Helper function to recursively calculate the depth of a component. + * + * @param currentComponent - The current component being inspected. + * @param currentLevel - The current level of depth in the tree. + * @returns An array of depth levels found for the component. + */ const getDepth = (currentComponent: NestedComponent, currentLevel: number): Array => { const levels = []; levels.push(currentLevel); - if (!currentComponent.parentCompoUid) { + // If the component has no parent UIDs, return the current levels + if (!currentComponent.uidsOfAllParents) { return levels; } - for (const parentUid of currentComponent.parentCompoUid) { + // Iterate over each parent UID to calculate their respective depths + for (const parentUid of currentComponent.uidsOfAllParents) { const parentComponent = findComponent(parentUid, components); if (parentComponent) { levels.push(...getDepth(parentComponent, currentLevel + 1));