mirror of https://github.com/artf/grapesjs.git
Browse Source
* Add tests for component wrapper * Refactor component data collection * Add data resolver to wrapper component * Fix types * Add collection data source to page * refactor get and set DataResolver to componentWrapper * Rename key to __rootData * add resolverCurrentItem * Make _resolverCurrentItem private * update ComponentWrapper tests * Fix componentWithCollectionsState * remove collectionsStateMap from Page * update component wrapper tests * fix component wrapper tests * return a copy of records for DataSource.getPath * Move all collection listeners to component with collection state * fix style sync in collection items * fix loop issue * update data collection tests * cleanup * update collection statemap on wrapper change * Add object test data for wrapper data resolver * cleanup * up unit test * remove duplicated code * cleanup event path * update test data to better names * improve component data collection performance * cleanup tests and types * fix performance issue for the new wrapper datasource * Undo updating component with datacolection tests * apply comments * Skip same path update --------- Co-authored-by: Artur Arseniev <artur.catch@hotmail.it>pull/6627/head
committed by
GitHub
12 changed files with 458 additions and 189 deletions
@ -0,0 +1,120 @@ |
|||
import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types'; |
|||
import DataResolverListener from '../../data_sources/model/DataResolverListener'; |
|||
import DataVariable, { DataVariableProps, DataVariableType } from '../../data_sources/model/DataVariable'; |
|||
import Components from '../../dom_components/model/Components'; |
|||
import Component from '../../dom_components/model/Component'; |
|||
import { ObjectAny } from '../../common'; |
|||
import DataSource from './DataSource'; |
|||
import { isArray } from 'underscore'; |
|||
|
|||
export type DataVariableMap = Record<string, DataVariableProps>; |
|||
|
|||
export type DataSourceRecords = DataVariableProps[] | DataVariableMap; |
|||
|
|||
export default class ComponentWithCollectionsState<DataResolverType> extends Component { |
|||
collectionsStateMap: DataCollectionStateMap = {}; |
|||
dataSourceWatcher?: DataResolverListener; |
|||
|
|||
constructor(props: any, opt: any) { |
|||
super(props, opt); |
|||
this.listenToPropsChange(); |
|||
} |
|||
|
|||
onCollectionsStateMapUpdate(collectionsStateMap: DataCollectionStateMap) { |
|||
this.collectionsStateMap = collectionsStateMap; |
|||
this.dataResolverWatchers?.onCollectionsStateMapUpdate?.(); |
|||
|
|||
this.components().forEach((cmp) => { |
|||
cmp.onCollectionsStateMapUpdate?.(collectionsStateMap); |
|||
}); |
|||
} |
|||
|
|||
syncOnComponentChange(model: Component, collection: Components, opts: any) { |
|||
const prev = this.collectionsStateMap; |
|||
this.collectionsStateMap = {}; |
|||
super.syncOnComponentChange(model, collection, opts); |
|||
this.collectionsStateMap = prev; |
|||
this.onCollectionsStateMapUpdate(prev); |
|||
} |
|||
|
|||
setDataResolver(dataResolver: DataResolverType | undefined) { |
|||
return this.set('dataResolver', dataResolver); |
|||
} |
|||
|
|||
get dataResolverProps(): DataResolverType | undefined { |
|||
return this.get('dataResolver'); |
|||
} |
|||
|
|||
protected listenToDataSource() { |
|||
const path = this.dataResolverPath; |
|||
if (!path) return; |
|||
|
|||
const { em, collectionsStateMap } = this; |
|||
this.dataSourceWatcher?.destroy(); |
|||
this.dataSourceWatcher = new DataResolverListener({ |
|||
em, |
|||
resolver: new DataVariable({ type: DataVariableType, path }, { em, collectionsStateMap }), |
|||
onUpdate: () => this.onDataSourceChange(), |
|||
}); |
|||
} |
|||
|
|||
protected listenToPropsChange() { |
|||
this.on(`change:dataResolver`, () => { |
|||
this.listenToDataSource(); |
|||
}); |
|||
|
|||
this.listenToDataSource(); |
|||
} |
|||
|
|||
protected get dataSourceProps(): DataVariableProps | undefined { |
|||
return this.get('dataResolver'); |
|||
} |
|||
|
|||
protected get dataResolverPath(): string | undefined { |
|||
return this.dataSourceProps?.path; |
|||
} |
|||
|
|||
protected onDataSourceChange() { |
|||
this.onCollectionsStateMapUpdate(this.collectionsStateMap); |
|||
} |
|||
|
|||
protected getDataSourceItems(): DataSourceRecords { |
|||
const dataSourceProps = this.dataSourceProps; |
|||
if (!dataSourceProps) return []; |
|||
const items = this.listDataSourceItems(dataSourceProps); |
|||
if (items && isArray(items)) { |
|||
return items; |
|||
} |
|||
|
|||
const clone = { ...items }; |
|||
return clone; |
|||
} |
|||
|
|||
protected listDataSourceItems(dataSource: DataSource | DataVariableProps): DataSourceRecords { |
|||
const path = dataSource instanceof DataSource ? dataSource.get('id')! : dataSource.path; |
|||
if (!path) return []; |
|||
let value = this.em.DataSources.getValue(path, []); |
|||
|
|||
const isDatasourceId = path.split('.').length === 1; |
|||
if (isDatasourceId) { |
|||
value = Object.entries(value).map(([_, value]) => value); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
protected getItemKey(items: DataVariableProps[] | { [x: string]: DataVariableProps }, index: number) { |
|||
return isArray(items) ? index : Object.keys(items)[index]; |
|||
} |
|||
|
|||
private removePropsListeners() { |
|||
this.off(`change:dataResolver`); |
|||
this.dataSourceWatcher?.destroy(); |
|||
this.dataSourceWatcher = undefined; |
|||
} |
|||
|
|||
destroy(options?: ObjectAny): false | JQueryXHR { |
|||
this.removePropsListeners(); |
|||
return super.destroy(options); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export const keyRootData = '__rootData'; |
|||
Loading…
Reference in new issue