From 29d983ea7082b1625d904b7b1423c03ca0e05efa Mon Sep 17 00:00:00 2001 From: mohamedsalem401 Date: Wed, 8 Jan 2025 12:57:28 +0200 Subject: [PATCH] Fix collection items propagation --- .../model/ComponentDynamicValueWatcher.ts | 3 +- .../src/dom_components/model/Components.ts | 4 +- .../src/dom_components/model/SymbolUtils.ts | 18 +++++-- .../core/src/dom_components/model/types.ts | 3 +- .../CollectionComponent.ts | 50 ++++++++++++++++++- .../__snapshots__/CollectionComponent.ts.snap | 2 +- 6 files changed, 70 insertions(+), 10 deletions(-) diff --git a/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts b/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts index b0331c500..4ad259d94 100644 --- a/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts +++ b/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts @@ -2,9 +2,10 @@ import { ObjectAny } from '../../common'; import { CollectionVariableType } from '../../data_sources/model/collection_component/constants'; import { CollectionsStateMap } from '../../data_sources/model/collection_component/types'; import EditorModel from '../../editor/model/Editor'; -import Component, { keyCollectionsStateMap } from './Component'; +import Component from './Component'; import { DynamicWatchersOptions } from './DynamicValueWatcher'; import { DynamicValueWatcher } from './DynamicValueWatcher'; +import { getSymbolsToUpdate } from './SymbolUtils'; export class ComponentDynamicValueWatcher { private propertyWatcher: DynamicValueWatcher; diff --git a/packages/core/src/dom_components/model/Components.ts b/packages/core/src/dom_components/model/Components.ts index df2e1f51e..1c6635b8c 100644 --- a/packages/core/src/dom_components/model/Components.ts +++ b/packages/core/src/dom_components/model/Components.ts @@ -335,7 +335,9 @@ Component> { ...parentCollectionsStateMap, }); - mdl.set('isCollectionItem', this.opt.isCollectionItem); + if (!mdl.get('isCollectionItem') && this.opt.isCollectionItem) { + mdl.set('isCollectionItem', this.opt.isCollectionItem); + } return mdl; } diff --git a/packages/core/src/dom_components/model/SymbolUtils.ts b/packages/core/src/dom_components/model/SymbolUtils.ts index 76ae4b139..8ea1e0589 100644 --- a/packages/core/src/dom_components/model/SymbolUtils.ts +++ b/packages/core/src/dom_components/model/SymbolUtils.ts @@ -130,8 +130,14 @@ export const logSymbol = (symb: Component, type: string, toUp: Component[], opts }; export const updateSymbolProps = (symbol: Component, opts: SymbolToUpOptions = {}) => { - const changed = symbol.changedAttributes() || {}; - const attrs = changed.attributes || {}; + const changed = { + ...(symbol.changedAttributes() || {}), + ...symbol.componentDVListener.getDynamicPropsDefs(), + }; + const attrs = { + ...(changed.attributes || {}), + ...symbol.componentDVListener.getDynamicAttributesDefs(), + }; delete changed.status; delete changed.open; delete changed[keySymbols]; @@ -148,7 +154,9 @@ export const updateSymbolProps = (symbol: Component, opts: SymbolToUpOptions = { const toUp = getSymbolsToUpdate(symbol, opts); // Avoid propagating overrides to other symbols keys(changed).map((prop) => { - if (isSymbolOverride(symbol, prop)) delete changed[prop]; + const shouldPropagate = + !isSymbolOverride(symbol, prop) || (symbol.get('isCollectionItem') && !opts.fromDataSource); + if (!shouldPropagate) delete changed[prop]; }); logSymbol(symbol, 'props', toUp, { opts, changed }); @@ -156,7 +164,9 @@ export const updateSymbolProps = (symbol: Component, opts: SymbolToUpOptions = { const propsChanged = { ...changed }; // Avoid updating those with override keys(propsChanged).map((prop) => { - if (isSymbolOverride(child, prop)) delete propsChanged[prop]; + const shouldPropagate = + !isSymbolOverride(child, prop) || (child.get('isCollectionItem') && !opts.fromDataSource); + if (!shouldPropagate) delete propsChanged[prop]; }); child.set(propsChanged, { fromInstance: symbol, ...opts }); }); diff --git a/packages/core/src/dom_components/model/types.ts b/packages/core/src/dom_components/model/types.ts index 0bda043b6..d10f34f3c 100644 --- a/packages/core/src/dom_components/model/types.ts +++ b/packages/core/src/dom_components/model/types.ts @@ -1,3 +1,4 @@ +import { DynamicWatchersOptions } from './DynamicValueWatcher'; import Frame from '../../canvas/model/Frame'; import { AddOptions, Nullable, OptionAsDocument } from '../../common'; import EditorModel from '../../editor/model/Editor'; @@ -253,7 +254,7 @@ export interface ComponentProperties { [key: string]: any; } -export interface SymbolToUpOptions { +export interface SymbolToUpOptions extends DynamicWatchersOptions { changed?: string; fromInstance?: boolean; noPropagate?: boolean; diff --git a/packages/core/test/specs/data_sources/model/collection_component/CollectionComponent.ts b/packages/core/test/specs/data_sources/model/collection_component/CollectionComponent.ts index e0a439618..b726cb4d5 100644 --- a/packages/core/test/specs/data_sources/model/collection_component/CollectionComponent.ts +++ b/packages/core/test/specs/data_sources/model/collection_component/CollectionComponent.ts @@ -1,4 +1,3 @@ -import { isSymbol } from 'underscore'; import { Component, DataRecord, DataSource, DataSourceManager } from '../../../../../src'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { @@ -6,7 +5,6 @@ import { CollectionVariableType, } from '../../../../../src/data_sources/model/collection_component/constants'; import { CollectionStateVariableType } from '../../../../../src/data_sources/model/collection_component/types'; -import { keySymbol } from '../../../../../src/dom_components/model/Component'; import EditorModel from '../../../../../src/editor/model/Editor'; import { filterObjectForSnapshot, setupTestEditor } from '../../../../common'; import { getSymbolMain, getSymbolTop } from '../../../../../src/dom_components/model/SymbolUtils'; @@ -94,6 +92,7 @@ describe('Collection component', () => { let cmp: Component; let firstChild!: Component; let secondChild!: Component; + let thirdChild!: Component; beforeEach(() => { cmp = wrapper.components({ @@ -123,6 +122,7 @@ describe('Collection component', () => { firstChild = cmp.components().at(0); secondChild = cmp.components().at(1); + thirdChild = cmp.components().at(2); }); test('Evaluating to static value', () => { @@ -141,6 +141,52 @@ describe('Collection component', () => { expect(secondChild.get('content')).toBe('user2'); expect(secondChild.get('custom_property')).toBe('user2'); }); + + test('Updating the value to a static value', async () => { + firstChild.set('content', 'new_content_value'); + expect(firstChild.get('content')).toBe('new_content_value'); + expect(secondChild.get('content')).toBe('new_content_value'); + + firstRecord.set('user', 'wrong_value'); + expect(firstChild.get('content')).toBe('new_content_value'); + expect(secondChild.get('content')).toBe('new_content_value'); + }); + + test('Updating the value to a diffirent collection variable', async () => { + firstChild.set('content', { + // @ts-ignore + type: CollectionVariableType, + variable_type: CollectionStateVariableType.current_item, + path: 'age', + }); + expect(firstChild.get('content')).toBe('12'); + expect(secondChild.get('content')).toBe('14'); + + firstRecord.set('age', 'new_value_12'); + secondRecord.set('age', 'new_value_14'); + + firstRecord.set('user', 'wrong_value'); + secondRecord.set('user', 'wrong_value'); + + expect(firstChild.get('content')).toBe('new_value_12'); + expect(secondChild.get('content')).toBe('new_value_14'); + }); + + test('Updating the value to a diffirent dynamic variable', async () => { + firstChild.set('content', { + // @ts-ignore + type: DataVariableType, + path: 'my_data_source_id.user2.user', + }); + expect(firstChild.get('content')).toBe('user2'); + expect(secondChild.get('content')).toBe('user2'); + expect(thirdChild.get('content')).toBe('user2'); + + secondRecord.set('user', 'new_value'); + expect(firstChild.get('content')).toBe('new_value'); + expect(secondChild.get('content')).toBe('new_value'); + expect(thirdChild.get('content')).toBe('new_value'); + }); }); test('Attributes', () => { diff --git a/packages/core/test/specs/data_sources/model/collection_component/__snapshots__/CollectionComponent.ts.snap b/packages/core/test/specs/data_sources/model/collection_component/__snapshots__/CollectionComponent.ts.snap index df0160aa1..f0f2cc993 100644 --- a/packages/core/test/specs/data_sources/model/collection_component/__snapshots__/CollectionComponent.ts.snap +++ b/packages/core/test/specs/data_sources/model/collection_component/__snapshots__/CollectionComponent.ts.snap @@ -22,7 +22,7 @@ exports[`Collection component Stringfication Collection with dynamic datasource "type": "parent-collection-variable", "variable_type": "current_item", }, - "isCollectionItem": false, + "isCollectionItem": true, "property_trait": { "path": "user", "type": "parent-collection-variable",