From 2f43b5cfb465bdb804745afc89d6552fd9ec9345 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Fri, 28 Nov 2025 12:27:37 +0400 Subject: [PATCH] Up wrapper api collections (#6664) * Add getCollectionsState to ComponentWrapper * Add DataFieldPrimitiveType to DataSourceManager module --- packages/core/src/data_sources/index.ts | 10 +++- .../model/ComponentWithCollectionsState.ts | 2 +- .../src/data_sources/model/DataVariable.ts | 12 +--- packages/core/src/data_sources/types.ts | 12 ++-- .../dom_components/model/ComponentWrapper.ts | 60 +++++++++++++------ .../dom_components/model/ComponentWrapper.ts | 4 +- 6 files changed, 62 insertions(+), 38 deletions(-) diff --git a/packages/core/src/data_sources/index.ts b/packages/core/src/data_sources/index.ts index fb737164d..0c0c69c96 100644 --- a/packages/core/src/data_sources/index.ts +++ b/packages/core/src/data_sources/index.ts @@ -36,7 +36,14 @@ import { DataCollectionStateType } from './model/data_collection/types'; import DataRecord from './model/DataRecord'; import DataSource from './model/DataSource'; import DataSources from './model/DataSources'; -import { DataCollectionKeys, DataComponentTypes, DataRecordProps, DataSourceProps, DataSourcesEvents } from './types'; +import { + DataCollectionKeys, + DataComponentTypes, + DataFieldPrimitiveType, + DataRecordProps, + DataSourceProps, + DataSourcesEvents, +} from './types'; export default class DataSourceManager extends ItemManagerModule { storageKey = 'dataSources'; @@ -44,6 +51,7 @@ export default class DataSourceManager extends ItemManagerModule extends Com this.onCollectionsStateMapUpdate(this.collectionsStateMap); } - protected getDataSourceItems(): DataSourceRecords { + getDataSourceItems(): DataSourceRecords { const { dataSourceProps } = this; if (!dataSourceProps) return []; diff --git a/packages/core/src/data_sources/model/DataVariable.ts b/packages/core/src/data_sources/model/DataVariable.ts index 356247e98..0f9bcf191 100644 --- a/packages/core/src/data_sources/model/DataVariable.ts +++ b/packages/core/src/data_sources/model/DataVariable.ts @@ -163,24 +163,16 @@ export default class DataVariable extends Model { } if (variableType === 'currentItem') { - return ( - DataVariable.resolveCurrentItem(collectionItem as DataCollectionState, path, collectionId, em) ?? defaultValue - ); + return DataVariable.resolveCurrentItem(collectionItem as DataCollectionState, path) ?? defaultValue; } const state = collectionItem as DataCollectionState; return state[variableType] ?? defaultValue; } - private static resolveCurrentItem( - collectionItem: DataCollectionState, - path: string | undefined, - collectionId: string, - em: EditorModel, - ) { + private static resolveCurrentItem(collectionItem: DataCollectionState, path: string | undefined) { const currentItem = collectionItem.currentItem; if (!currentItem) { - em.logError(`Current item is missing for collection: ${collectionId}`); return; } diff --git a/packages/core/src/data_sources/types.ts b/packages/core/src/data_sources/types.ts index 3fd251c90..7545c0510 100644 --- a/packages/core/src/data_sources/types.ts +++ b/packages/core/src/data_sources/types.ts @@ -86,28 +86,28 @@ export interface DataFieldSchemaBase { } export interface DataFieldSchemaString extends DataFieldSchemaBase { - type: DataFieldPrimitiveType.string; + type: `${DataFieldPrimitiveType.string}`; enum?: string[]; } export interface DataFieldSchemaNumber extends DataFieldSchemaBase { - type: DataFieldPrimitiveType.number; + type: `${DataFieldPrimitiveType.number}`; } export interface DataFieldSchemaBoolean extends DataFieldSchemaBase { - type: DataFieldPrimitiveType.boolean; + type: `${DataFieldPrimitiveType.boolean}`; } export interface DataFieldSchemaDate extends DataFieldSchemaBase { - type: DataFieldPrimitiveType.date; + type: `${DataFieldPrimitiveType.date}`; } export interface DataFieldSchemaJSON extends DataFieldSchemaBase { - type: DataFieldPrimitiveType.json; + type: `${DataFieldPrimitiveType.json}`; } export interface DataFieldSchemaRelation extends DataFieldSchemaBase { - type: DataFieldPrimitiveType.relation; + type: `${DataFieldPrimitiveType.relation}`; /** * The target data source ID */ diff --git a/packages/core/src/dom_components/model/ComponentWrapper.ts b/packages/core/src/dom_components/model/ComponentWrapper.ts index f8ff2f97e..328a21c9c 100644 --- a/packages/core/src/dom_components/model/ComponentWrapper.ts +++ b/packages/core/src/dom_components/model/ComponentWrapper.ts @@ -1,8 +1,8 @@ -import { isNumber, isString, isUndefined } from 'underscore'; +import { all, isArray, isNumber, isUndefined } from 'underscore'; import ComponentWithCollectionsState from '../../data_sources/model/ComponentWithCollectionsState'; import DataResolverListener from '../../data_sources/model/DataResolverListener'; import { DataVariableProps } from '../../data_sources/model/DataVariable'; -import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types'; +import { DataCollectionStateMap, DataCollectionStateType } from '../../data_sources/model/data_collection/types'; import { DataCollectionKeys } from '../../data_sources/types'; import { attrToString } from '../../utils/dom'; import Component from './Component'; @@ -14,7 +14,7 @@ type ResolverCurrentItemType = string | number; export default class ComponentWrapper extends ComponentWithCollectionsState { dataSourceWatcher?: DataResolverListener; - private _resolverCurrentItem?: ResolverCurrentItemType = 0; + private _resolverCurrentItem: ResolverCurrentItemType = 0; private _isWatchingCollectionStateMap = false; get defaults() { @@ -133,6 +133,43 @@ export default class ComponentWrapper extends ComponentWithCollectionsState | undefined; + let currentItem: Record | undefined; + let nextItem: Record | undefined; + + const allItems: Record | Record[] = this.getDataSourceItems(); + const allItemsArray = isArray(allItems) ? allItems : Object.values(allItems || {}); + let currentIndex = resolverCurrentItem; + + if (isNumber(resolverCurrentItem)) { + currentItem = allItemsArray[resolverCurrentItem]; + prevItem = allItemsArray[resolverCurrentItem - 1]; + nextItem = allItemsArray[resolverCurrentItem + 1]; + } else { + const entries = Object.entries(allItems).map(([id, value]) => ({ id, ...value })); + const idx = entries.findIndex((it) => it?.id === resolverCurrentItem); + currentIndex = idx; + currentItem = allItemsArray[idx]; + prevItem = allItemsArray[idx - 1]; + nextItem = allItemsArray[idx + 1]; + } + + return { + ...result, + prevItem, + nextItem, + [DataCollectionStateType.currentItem]: currentItem, + [DataCollectionStateType.currentIndex]: currentIndex, + [DataCollectionStateType.totalItems]: allItemsArray.length, + }; + } + protected onDataSourceChange() { this.onCollectionsStateMapUpdate(this.getCollectionsStateMap()); } @@ -156,23 +193,10 @@ export default class ComponentWrapper extends ComponentWithCollectionsState { test('wrapper should handle objects as collection state', () => { wrapper.setDataResolver(createDataResolver('contentDataSource.productsById.data')); - wrapper.setResolverCurrentItem('product1'); + wrapper.setResolverCurrentItem('product2'); const child = appendChildWithTitle('title'); - expect(child.get('title')).toBe(productsById.product1.title); + expect(child.get('title')).toBe(productsById.product2.title); }); test('wrapper should handle default data source records', () => {