diff --git a/packages/core/src/data_sources/model/collection_component/CollectionComponent.ts b/packages/core/src/data_sources/model/collection_component/CollectionComponent.ts index 1ce8cdc15..1d5c99f7f 100644 --- a/packages/core/src/data_sources/model/collection_component/CollectionComponent.ts +++ b/packages/core/src/data_sources/model/collection_component/CollectionComponent.ts @@ -1,4 +1,3 @@ -import { ComponentDefinitionDefined } from './../../../dom_components/model/types'; import { isArray } from 'underscore'; import Component from '../../../dom_components/model/Component'; import { ComponentDefinition, ComponentOptions, ComponentProperties } from '../../../dom_components/model/types'; @@ -6,6 +5,7 @@ import { toLowerCase } from '../../../utils/mixins'; import { ConditionDefinition } from '../conditional_variables/DataCondition'; import DataSource from '../DataSource'; import { DataVariableType } from '../DataVariable'; +import { ObjectAny } from '../../../common'; export const CollectionVariableType = 'collection-component'; // Represents the type for defining a loop’s data source. @@ -48,8 +48,8 @@ export default class CollectionComponent extends Component { start_index = 0, end_index = Number.MAX_VALUE, dataSource = [], - } = config - let items: CollectionStateVariables[] = []; + } = config; + let items: any[] = []; switch (true) { case isArray(dataSource): items = dataSource; @@ -58,14 +58,20 @@ export default class CollectionComponent extends Component { const id = dataSource.get('id')!; const resolvedPath = opt.em.DataSources.getValue(id, []); const keys = Object.keys(resolvedPath); - items = keys.map(key => resolvedPath[key]); + items = keys.map(key => ({ + type: DataVariableType, + path: id + '.' + key, + })); break; case typeof dataSource === 'object' && dataSource.type === DataVariableType: const pathArr = dataSource.path.split('.'); if (pathArr.length === 1) { const resolvedPath = opt.em.DataSources.getValue(dataSource.path, []); const keys = Object.keys(resolvedPath); - items = keys.map(key => resolvedPath[key]); + items = keys.map(key => ({ + type: DataVariableType, + path: id + '.' + key, + })); } else { items = opt.em.DataSources.getValue(dataSource.path, []); } @@ -73,12 +79,36 @@ export default class CollectionComponent extends Component { default: } - const components: ComponentDefinitionDefined[] = []; + const components: ComponentDefinition[] = []; const resolvedStartIndex = Math.max(0, start_index); const resolvedEndIndex = Math.min(items.length - 1, end_index); + const item = items[resolvedStartIndex]; + let symbolMain; + const total_items = resolvedEndIndex - resolvedStartIndex + 1; + const innerMostCollectionItem = { + collection_name, + current_index: resolvedStartIndex, + current_item: item, + start_index: resolvedStartIndex, + end_index: resolvedEndIndex, + total_items: total_items, + remaining_items: total_items - (resolvedStartIndex + 1), + }; + + const allCollectionItem = { + ...props.collectionsItems, + [innerMostCollectionItem.collection_name ? innerMostCollectionItem.collection_name : 'innerMostCollectionItem']: + innerMostCollectionItem, + innerMostCollectionItem + } + const { clonedBlock, overrideKeys } = resolveBlockValues(allCollectionItem, block); + const type = opt.em.Components.getType(clonedBlock?.type || 'default'); + const model = type.model; + const symbol = new model(clonedBlock, opt); + symbolMain = opt.em.Components.addSymbol(symbol); + for (let index = resolvedStartIndex; index <= resolvedEndIndex; index++) { const item = items[index]; - const total_items = resolvedEndIndex - resolvedStartIndex + 1; const innerMostCollectionItem = { collection_name, current_index: index, @@ -89,15 +119,33 @@ export default class CollectionComponent extends Component { remaining_items: total_items - (index + 1), }; - const allCollectionItems = { + const allCollectionItem = { ...props.collectionsItems, [innerMostCollectionItem.collection_name ? innerMostCollectionItem.collection_name : 'innerMostCollectionItem']: innerMostCollectionItem, innerMostCollectionItem } + const { overrideKeys } = resolveBlockValues(allCollectionItem, block); + const instance = opt.em.Components.addSymbol(symbolMain!); + const children: any[] = [] + Object.keys(overrideKeys).length && instance!.setSymbolOverride(Object.keys(overrideKeys)); + instance!.set(overrideKeys); + for (let i = 0; i < instance!.components().length; i++) { + const childBlock = block['components'][i]; + const { overrideKeys } = resolveBlockValues(allCollectionItem, deepCloneObject(childBlock)); + const child = opt.em.Components.addSymbol(symbolMain!.components().at(i)) + Object.keys(overrideKeys).length && child!.setSymbolOverride(Object.keys(overrideKeys)); + child!.set(overrideKeys) + children.push(child); + } - const component = resolveBlockValues(allCollectionItems, block); - components.push(component); + const componentJSON = instance?.toJSON(); + const cmpDefinition = { + ...componentJSON, + components: children + }; + + components.push(cmpDefinition); } const conditionalCmptDef = { @@ -139,9 +187,10 @@ function deepCloneObject | null | undefined>(obj: return clonedObj as T; } -function resolveBlockValues(context: any, block: any): any { +function resolveBlockValues(context: any, block: any) { const { innerMostCollectionItem } = context; const clonedBlock = deepCloneObject(block); + const overrideKeys: ObjectAny = {}; if (typeof clonedBlock === 'object' && clonedBlock !== null) { const blockKeys = Object.keys(clonedBlock); @@ -149,12 +198,13 @@ function resolveBlockValues(context: any, block: any): any { for (const key of blockKeys) { let blockValue = clonedBlock[key]; if (key === 'collectionDefinition') continue; + let shouldBeOverridden = false; if (typeof blockValue === 'object' && blockValue !== null) { + const collectionItem = blockValue.collection_name + ? context[blockValue.collection_name] + : innerMostCollectionItem; if (blockValue.type === 'parent-collection-variable') { - const collectionItem = blockValue.collection_name - ? context[blockValue.collection_name] - : innerMostCollectionItem; if (!collectionItem) { throw new Error( `Collection not found: ${blockValue.collection_name || 'default collection'}` @@ -162,38 +212,42 @@ function resolveBlockValues(context: any, block: any): any { } if (blockValue.variable_type === 'current_item') { - clonedBlock[key] = blockValue.path - ? resolvePathValue(collectionItem.current_item, blockValue.path) - : JSON.stringify(collectionItem.current_item); + if (collectionItem.current_item.type === DataVariableType) { + const path = collectionItem.current_item.path ? `${collectionItem.current_item.path}.${blockValue.path}` : blockValue.path; + clonedBlock[key] = { + ...collectionItem.current_item, + path + }; + } } else { clonedBlock[key] = collectionItem[blockValue.variable_type]; } + + shouldBeOverridden = true; } else if (Array.isArray(blockValue)) { // Resolve each item in the array - clonedBlock[key] = blockValue.map((arrayItem: any) => - typeof arrayItem === 'object' ? resolveBlockValues(context, arrayItem) : arrayItem - ); + clonedBlock[key] = blockValue.map((arrayItem: any) => { + const { clonedBlock, overrideKeys: itemOverrideKeys } = resolveBlockValues(context, arrayItem) + if (Object.keys(itemOverrideKeys).length > 0) { + shouldBeOverridden = true; + } + return typeof arrayItem === 'object' ? clonedBlock : arrayItem + }); } else { - clonedBlock[key] = resolveBlockValues(context, blockValue); - } - } - } - } - - return clonedBlock; -} + const { clonedBlock, overrideKeys: itemOverrideKeys } = resolveBlockValues(context, blockValue).clonedBlock; + clonedBlock[key] = clonedBlock; -function resolvePathValue(object: any, path: string): any { - const pathSegments = path.split('.'); - let resolvedValue = object; + if (Object.keys(itemOverrideKeys).length > 0) { + shouldBeOverridden = true; + } + } - for (const segment of pathSegments) { - if (resolvedValue && typeof resolvedValue === 'object' && segment in resolvedValue) { - resolvedValue = resolvedValue[segment]; - } else { - return undefined; // Return undefined if the path doesn't exist + if (shouldBeOverridden && key !== 'components') { + overrideKeys[key] = clonedBlock[key] + } + } } } - return resolvedValue; + return { clonedBlock, overrideKeys }; }