Browse Source

Add collection variable component

collection-component
mohamedsalem401 2 years ago
parent
commit
19007fabf0
  1. 12
      packages/core/src/data_sources/model/DataVariableListenerManager.ts
  2. 1
      packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts
  3. 53
      packages/core/src/data_sources/model/data_collection/ComponentDataCollectionVariable.ts
  4. 24
      packages/core/src/data_sources/model/data_collection/ComponentDataCollectionVariableView.ts
  5. 42
      packages/core/src/data_sources/model/data_collection/DataCollectionVariable.ts
  6. 5
      packages/core/src/data_sources/model/utils.ts
  7. 4
      packages/core/src/data_sources/types.ts
  8. 9
      packages/core/src/dom_components/index.ts
  9. 2
      packages/core/test/specs/data_sources/model/data_collection/ComponentDataCollection.ts
  10. 69
      packages/core/test/specs/data_sources/model/data_collection/ComponentDataCollectionVariable.ts

12
packages/core/src/data_sources/model/DataVariableListenerManager.ts

@ -7,7 +7,7 @@ import { DynamicValue } from '../types';
import { DataCondition, ConditionalVariableType } from './conditional_variables/DataCondition'; import { DataCondition, ConditionalVariableType } from './conditional_variables/DataCondition';
import ComponentDataVariable from './ComponentDataVariable'; import ComponentDataVariable from './ComponentDataVariable';
import { CollectionVariableType } from './data_collection/constants'; import { CollectionVariableType } from './data_collection/constants';
import CollectionVariable from './data_collection/CollectionVariable'; import DataCollectionVariable from './data_collection/DataCollectionVariable';
export interface DynamicVariableListenerManagerOptions { export interface DynamicVariableListenerManagerOptions {
em: EditorModel; em: EditorModel;
@ -44,11 +44,7 @@ export default class DynamicVariableListenerManager {
let dataListeners: DataVariableListener[] = []; let dataListeners: DataVariableListener[] = [];
switch (type) { switch (type) {
case CollectionVariableType: case CollectionVariableType:
const collectionVariable = dynamicVariable as CollectionVariable; dataListeners = this.listenToDataCollectionVariable(dynamicVariable as DataCollectionVariable);
if (collectionVariable.hasDynamicValue()) {
dataListeners = this.listenToDataVariable(collectionVariable.dataVariable!, em);
}
break; break;
case DataVariableType: case DataVariableType:
dataListeners = this.listenToDataVariable(dynamicVariable as DataVariable | ComponentDataVariable, em); dataListeners = this.listenToDataVariable(dynamicVariable as DataVariable | ComponentDataVariable, em);
@ -86,6 +82,10 @@ export default class DynamicVariableListenerManager {
return dataListeners; return dataListeners;
} }
private listenToDataCollectionVariable(dataVariable: DataCollectionVariable) {
return [{ obj: dataVariable, event: 'change:value' }];
}
private removeListeners() { private removeListeners() {
this.dataListeners.forEach((ls) => this.model.stopListening(ls.obj, ls.event, this.onChange)); this.dataListeners.forEach((ls) => this.model.stopListening(ls.obj, ls.event, this.onChange));
this.dataListeners = []; this.dataListeners = [];

1
packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts

@ -95,6 +95,7 @@ export default class ComponentDataCollection extends Component {
}, },
{ em }, { em },
); );
new DynamicVariableListenerManager({ new DynamicVariableListenerManager({
em: em, em: em,
dataVariable, dataVariable,

53
packages/core/src/data_sources/model/data_collection/ComponentDataCollectionVariable.ts

@ -0,0 +1,53 @@
import Component, { keyCollectionsStateMap, keySymbolOvrd } from '../../../dom_components/model/Component';
import { ComponentOptions, ComponentProperties } from '../../../dom_components/model/types';
import { toLowerCase } from '../../../utils/mixins';
import DataCollectionVariable from './DataCollectionVariable';
import { CollectionVariableType, keyInnerCollectionState } from './constants';
import { DataCollectionStateMap, DataCollectionVariableDefinition } from './types';
export default class ComponentDataCollectionVariable extends Component {
datacollectionVariable: DataCollectionVariable;
get defaults() {
return {
// @ts-ignore
...super.defaults,
type: CollectionVariableType,
variableType: '',
path: '',
collectionName: keyInnerCollectionState,
};
}
constructor(props: DataCollectionVariableDefinition & ComponentProperties, opt: ComponentOptions) {
super(props, opt);
const em = opt.em;
const { type, variableType, path, collectionName } = props;
this.datacollectionVariable = new DataCollectionVariable(
{ type, variableType, path, collectionName },
{
em,
collectionsStateMap: this.get(keyCollectionsStateMap),
},
);
this.listenTo(this, `change:${keyCollectionsStateMap}`, this.handleCollectionsMapStateUpdate);
}
private handleCollectionsMapStateUpdate(m: any, v: DataCollectionStateMap, opts = {}) {
this.datacollectionVariable.updateCollectionsStateMap(v);
}
getDataValue() {
return this.datacollectionVariable.getDataValue();
}
getInnerHTML() {
return this.getDataValue();
}
static isComponent(el: HTMLElement) {
return toLowerCase(el.tagName) === CollectionVariableType;
}
}

24
packages/core/src/data_sources/model/data_collection/ComponentDataCollectionVariableView.ts

@ -0,0 +1,24 @@
import ComponentView from '../../../dom_components/view/ComponentView';
import DynamicVariableListenerManager from '../DataVariableListenerManager';
import ComponentDataCollectionVariable from './ComponentDataCollectionVariable';
export default class ComponentDataCollectionVariableView extends ComponentView<ComponentDataCollectionVariable> {
collectionVariableListener?: DynamicVariableListenerManager;
initialize(opt = {}) {
super.initialize(opt);
this.postRender();
this.collectionVariableListener = new DynamicVariableListenerManager({
em: this.em!,
dataVariable: this.model.datacollectionVariable,
updateValueFromDataVariable: this.postRender,
});
}
postRender() {
const { model, el } = this;
el.innerHTML = model.datacollectionVariable.getDataValue();
super.postRender();
}
}

42
packages/core/src/data_sources/model/data_collection/CollectionVariable.ts → packages/core/src/data_sources/model/data_collection/DataCollectionVariable.ts

@ -2,16 +2,31 @@ import { DataCollectionVariableDefinition } from './types';
import { Model } from '../../../common'; import { Model } from '../../../common';
import EditorModel from '../../../editor/model/Editor'; import EditorModel from '../../../editor/model/Editor';
import DataVariable, { DataVariableType } from '../DataVariable'; import DataVariable, { DataVariableType } from '../DataVariable';
import { keyInnerCollectionState } from './constants'; import { CollectionVariableType, keyInnerCollectionState } from './constants';
import { DataCollectionState, DataCollectionStateMap } from './types'; import { DataCollectionState, DataCollectionStateMap } from './types';
import DynamicVariableListenerManager from '../DataVariableListenerManager';
type ResolvedDataCollectionVariable = DataCollectionVariableDefinition & {
value?: any;
};
export default class CollectionVariable extends Model<DataCollectionVariableDefinition> { export default class DataCollectionVariable extends Model<ResolvedDataCollectionVariable> {
em: EditorModel; em: EditorModel;
collectionsStateMap: DataCollectionStateMap; collectionsStateMap: DataCollectionStateMap;
dataVariable?: DataVariable; dataVariable?: DataVariable;
dynamicValueListener?: DynamicVariableListenerManager;
defaults(): Partial<ResolvedDataCollectionVariable> {
return {
type: CollectionVariableType,
variableType: undefined,
path: '',
collectionName: keyInnerCollectionState,
value: undefined,
};
}
constructor( constructor(
attrs: DataCollectionVariableDefinition, attrs: ResolvedDataCollectionVariable,
options: { options: {
em: EditorModel; em: EditorModel;
collectionsStateMap: DataCollectionStateMap; collectionsStateMap: DataCollectionStateMap;
@ -20,7 +35,6 @@ export default class CollectionVariable extends Model<DataCollectionVariableDefi
super(attrs, options); super(attrs, options);
this.em = options.em; this.em = options.em;
this.collectionsStateMap = options.collectionsStateMap; this.collectionsStateMap = options.collectionsStateMap;
this.updateDataVariable(); this.updateDataVariable();
} }
@ -34,10 +48,13 @@ export default class CollectionVariable extends Model<DataCollectionVariableDefi
if (resolvedValue?.type === DataVariableType) { if (resolvedValue?.type === DataVariableType) {
return this.dataVariable!.getDataValue(); return this.dataVariable!.getDataValue();
} }
return resolvedValue; return resolvedValue;
} }
private updateDataVariable() { private updateDataVariable() {
if (!this.collectionsStateMap) return { resolvedValue: undefined };
const resolvedValue = resolveCollectionVariable( const resolvedValue = resolveCollectionVariable(
this.attributes as DataCollectionVariableDefinition, this.attributes as DataCollectionVariableDefinition,
this.collectionsStateMap, this.collectionsStateMap,
@ -48,13 +65,28 @@ export default class CollectionVariable extends Model<DataCollectionVariableDefi
if (resolvedValue?.type === DataVariableType) { if (resolvedValue?.type === DataVariableType) {
dataVariable = new DataVariable(resolvedValue, { em: this.em }); dataVariable = new DataVariable(resolvedValue, { em: this.em });
this.dataVariable = dataVariable; this.dataVariable = dataVariable;
this.dynamicValueListener?.destroy();
this.dynamicValueListener = new DynamicVariableListenerManager({
em: this.em,
dataVariable,
updateValueFromDataVariable: this.updateDataVariable,
});
} }
this.set('value', resolvedValue);
return { resolvedValue, dataVariable }; return { resolvedValue, dataVariable };
} }
updateCollectionsStateMap(collectionsStateMap: DataCollectionStateMap) {
this.collectionsStateMap = collectionsStateMap;
this.updateDataVariable();
}
destroy() { destroy() {
return this.dataVariable?.destroy?.() || super.destroy(); this.dynamicValueListener?.destroy();
this.dataVariable?.destroy();
return super.destroy();
} }
} }

5
packages/core/src/data_sources/model/utils.ts

@ -1,8 +1,7 @@
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import { DynamicValue, DynamicValueDefinition } from '../types'; import { DynamicValue, DynamicValueDefinition } from '../types';
import { DataCollectionStateMap } from './data_collection/types'; import { DataCollectionStateMap } from './data_collection/types';
import CollectionVariable from './data_collection/CollectionVariable'; import DataCollectionVariable from './data_collection/DataCollectionVariable';
import { DataCollectionVariableDefinition } from './data_collection/types';
import { CollectionVariableType } from './data_collection/constants'; import { CollectionVariableType } from './data_collection/constants';
import { ConditionalVariableType, DataCondition } from './conditional_variables/DataCondition'; import { ConditionalVariableType, DataCondition } from './conditional_variables/DataCondition';
import DataVariable, { DataVariableType } from './DataVariable'; import DataVariable, { DataVariableType } from './DataVariable';
@ -52,7 +51,7 @@ export function getDynamicValueInstance(
} }
case CollectionVariableType: { case CollectionVariableType: {
// @ts-ignore // @ts-ignore
dynamicVariable = new CollectionVariable(valueDefinition, options); dynamicVariable = new DataCollectionVariable(valueDefinition, options);
break; break;
} }
default: default:

4
packages/core/src/data_sources/types.ts

@ -1,5 +1,5 @@
import { ObjectAny } from '../common'; import { ObjectAny } from '../common';
import CollectionVariable from './model/data_collection/CollectionVariable'; import DataCollectionVariable from './model/data_collection/DataCollectionVariable';
import { DataCollectionVariableDefinition } from './model/data_collection/types'; import { DataCollectionVariableDefinition } from './model/data_collection/types';
import ComponentDataVariable from './model/ComponentDataVariable'; import ComponentDataVariable from './model/ComponentDataVariable';
import DataRecord from './model/DataRecord'; import DataRecord from './model/DataRecord';
@ -7,7 +7,7 @@ import DataRecords from './model/DataRecords';
import DataVariable, { DataVariableDefinition } from './model/DataVariable'; import DataVariable, { DataVariableDefinition } from './model/DataVariable';
import { ConditionalVariableDefinition, DataCondition } from './model/conditional_variables/DataCondition'; import { ConditionalVariableDefinition, DataCondition } from './model/conditional_variables/DataCondition';
export type DynamicValue = DataVariable | ComponentDataVariable | DataCondition | CollectionVariable; export type DynamicValue = DataVariable | ComponentDataVariable | DataCondition | DataCollectionVariable;
export type DynamicValueDefinition = export type DynamicValueDefinition =
| DataVariableDefinition | DataVariableDefinition
| ConditionalVariableDefinition | ConditionalVariableDefinition

9
packages/core/src/dom_components/index.ts

@ -130,7 +130,9 @@ import ComponentConditionalVariable from '../data_sources/model/conditional_vari
import ConditionalComponentView from '../data_sources/view/ComponentDynamicView'; import ConditionalComponentView from '../data_sources/view/ComponentDynamicView';
import ComponentDataCollection from '../data_sources/model/data_collection/ComponentDataCollection'; import ComponentDataCollection from '../data_sources/model/data_collection/ComponentDataCollection';
import ComponentDataCollectionView from '../data_sources/model/data_collection/ComponentDataCollectionView'; import ComponentDataCollectionView from '../data_sources/model/data_collection/ComponentDataCollectionView';
import { CollectionComponentType } from '../data_sources/model/data_collection/constants'; import { CollectionComponentType, CollectionVariableType } from '../data_sources/model/data_collection/constants';
import ComponentDataCollectionVariable from '../data_sources/model/data_collection/ComponentDataCollectionVariable';
import ComponentDataCollectionVariableView from '../data_sources/model/data_collection/ComponentDataCollectionVariableView';
export type ComponentEvent = export type ComponentEvent =
| 'component:create' | 'component:create'
@ -196,6 +198,11 @@ export interface CanMoveResult {
export default class ComponentManager extends ItemManagerModule<DomComponentsConfig, any> { export default class ComponentManager extends ItemManagerModule<DomComponentsConfig, any> {
componentTypes: ComponentStackItem[] = [ componentTypes: ComponentStackItem[] = [
{
id: CollectionVariableType,
model: ComponentDataCollectionVariable,
view: ComponentDataCollectionVariableView,
},
{ {
id: CollectionComponentType, id: CollectionComponentType,
model: ComponentDataCollection, model: ComponentDataCollection,

2
packages/core/test/specs/data_sources/model/data_collection/ComponentDataCollection.ts

@ -6,7 +6,7 @@ import {
} from '../../../../../src/data_sources/model/data_collection/constants'; } from '../../../../../src/data_sources/model/data_collection/constants';
import { DataCollectionStateVariableType } from '../../../../../src/data_sources/model/data_collection/types'; import { DataCollectionStateVariableType } from '../../../../../src/data_sources/model/data_collection/types';
import EditorModel from '../../../../../src/editor/model/Editor'; import EditorModel from '../../../../../src/editor/model/Editor';
import { filterObjectForSnapshot, setupTestEditor } from '../../../../common'; import { setupTestEditor } from '../../../../common';
import { getSymbolMain } from '../../../../../src/dom_components/model/SymbolUtils'; import { getSymbolMain } from '../../../../../src/dom_components/model/SymbolUtils';
import { ProjectData } from '../../../../../src/storage_manager'; import { ProjectData } from '../../../../../src/storage_manager';

69
packages/core/test/specs/data_sources/model/data_collection/ComponentDataCollectionVariable.ts

@ -0,0 +1,69 @@
import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import {
CollectionComponentType,
CollectionVariableType,
} from '../../../../../src/data_sources/model/data_collection/constants';
import { DataCollectionStateVariableType } from '../../../../../src/data_sources/model/data_collection/types';
import EditorModel from '../../../../../src/editor/model/Editor';
import { setupTestEditor } from '../../../../common';
describe('Collection component', () => {
let em: EditorModel;
let editor: Editor;
let dsm: DataSourceManager;
let dataSource: DataSource;
let wrapper: Component;
let firstRecord: DataRecord;
let secondRecord: DataRecord;
beforeEach(() => {
({ em, editor, dsm } = setupTestEditor());
wrapper = em.getWrapper()!;
dataSource = dsm.add({
id: 'my_data_source_id',
records: [
{ id: 'user1', user: 'user1', age: '12' },
{ id: 'user2', user: 'user2', age: '14' },
{ id: 'user3', user: 'user3', age: '16' },
],
});
firstRecord = dataSource.getRecord('user1')!;
secondRecord = dataSource.getRecord('user2')!;
});
afterEach(() => {
em.destroy();
});
test('Collection variable components', async () => {
const cmp = wrapper.components({
type: CollectionComponentType,
collectionDefinition: {
block: {
type: 'default',
components: [
{
type: CollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem,
path: 'user',
},
],
},
config: {
dataSource: {
type: DataVariableType,
path: 'my_data_source_id',
},
},
},
})[0];
const firstGrandchild = cmp.components().at(0).components().at(0);
expect(firstGrandchild.getInnerHTML()).toContain('user1');
const secondGrandchild = cmp.components().at(1).components().at(0);
expect(secondGrandchild.getInnerHTML()).toContain('user2');
});
});
Loading…
Cancel
Save