Browse Source

Refactoring

collection-component
Artur Arseniev 2 years ago
parent
commit
9040859741
  1. 2
      packages/core/src/data_sources/model/DataSource.ts
  2. 9
      packages/core/src/data_sources/model/DataVariable.ts
  3. 8
      packages/core/src/data_sources/model/DataVariableListenerManager.ts
  4. 8
      packages/core/src/data_sources/model/TraitDataVariable.ts
  5. 23
      packages/core/src/data_sources/model/conditional_variables/ComponentDataCondition.ts
  6. 24
      packages/core/src/data_sources/model/conditional_variables/Condition.ts
  7. 44
      packages/core/src/data_sources/model/conditional_variables/DataCondition.ts
  8. 7
      packages/core/src/data_sources/model/conditional_variables/LogicalGroupStatement.ts
  9. 27
      packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts
  10. 12
      packages/core/src/data_sources/model/data_collection/ComponentDataCollectionVariable.ts
  11. 23
      packages/core/src/data_sources/model/data_collection/DataCollectionVariable.ts
  12. 4
      packages/core/src/data_sources/model/data_collection/constants.ts
  13. 26
      packages/core/src/data_sources/model/data_collection/types.ts
  14. 21
      packages/core/src/data_sources/model/utils.ts
  15. 13
      packages/core/src/data_sources/types.ts
  16. 4
      packages/core/src/data_sources/view/ComponentDataConditionView.ts
  17. 4
      packages/core/src/data_sources/view/ComponentDynamicView.ts
  18. 18
      packages/core/src/dom_components/index.ts
  19. 6
      packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts
  20. 10
      packages/core/src/dom_components/model/DynamicValueWatcher.ts
  21. 9
      packages/core/src/dom_components/model/SymbolUtils.ts
  22. 18
      packages/core/src/domain_abstract/model/StyleableModel.ts
  23. 2
      packages/core/src/trait_manager/model/Trait.ts
  24. 31
      packages/core/test/specs/data_sources/model/conditional_variables/ComponentConditionalVariable.ts
  25. 11
      packages/core/test/specs/data_sources/model/conditional_variables/ConditionalStyles.ts
  26. 10
      packages/core/test/specs/data_sources/model/conditional_variables/ConditionalTraits.ts
  27. 39
      packages/core/test/specs/data_sources/model/conditional_variables/DataCondition.ts
  28. 102
      packages/core/test/specs/data_sources/model/data_collection/ComponentDataCollection.ts
  29. 24
      packages/core/test/specs/data_sources/model/data_collection/ComponentDataCollectionVariable.ts
  30. 132
      packages/core/test/specs/data_sources/model/data_collection/__snapshots__/ComponentDataCollection.ts.snap
  31. 20
      packages/core/test/specs/data_sources/model/data_collection/__snapshots__/ComponentDataCollectionVariable.ts.snap
  32. 6
      packages/core/test/specs/data_sources/model/data_collection/__snapshots__/nestedComponentDataCollections.ts.snap
  33. 50
      packages/core/test/specs/data_sources/model/data_collection/nestedComponentDataCollections.ts

2
packages/core/src/data_sources/model/DataSource.ts

@ -31,7 +31,7 @@
import { AddOptions, collectionEvents, CombinedModelConstructorOptions, Model, RemoveOptions } from '../../common'; import { AddOptions, collectionEvents, CombinedModelConstructorOptions, Model, RemoveOptions } from '../../common';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import { DataSourceTransformers, DataSourceType, DataSourceProps, RecordPropsType, DataRecordProps } from '../types'; import { DataSourceTransformers, DataSourceType, DataSourceProps, DataRecordProps } from '../types';
import DataRecord from './DataRecord'; import DataRecord from './DataRecord';
import DataRecords from './DataRecords'; import DataRecords from './DataRecords';
import DataSources from './DataSources'; import DataSources from './DataSources';

9
packages/core/src/data_sources/model/DataVariable.ts

@ -3,11 +3,12 @@ import EditorModel from '../../editor/model/Editor';
import { stringToPath } from '../../utils/mixins'; import { stringToPath } from '../../utils/mixins';
export const DataVariableType = 'data-variable'; export const DataVariableType = 'data-variable';
export type DataVariableDefinition = {
export interface DataVariableProps {
type: typeof DataVariableType; type: typeof DataVariableType;
path: string; path: string;
defaultValue?: string; defaultValue?: string;
}; }
export default class DataVariable extends Model { export default class DataVariable extends Model {
em?: EditorModel; em?: EditorModel;
@ -20,8 +21,8 @@ export default class DataVariable extends Model {
}; };
} }
constructor(attrs: DataVariableDefinition, options: any) { constructor(props: DataVariableProps, options: any) {
super(attrs, options); super(props, options);
this.em = options.em; this.em = options.em;
this.listenToDataSource(); this.listenToDataSource();
} }

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

@ -4,9 +4,9 @@ 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 { DynamicValue } from '../types'; import { DynamicValue } from '../types';
import { DataCondition, ConditionalVariableType } from './conditional_variables/DataCondition'; import { DataCondition, DataConditionType } from './conditional_variables/DataCondition';
import ComponentDataVariable from './ComponentDataVariable'; import ComponentDataVariable from './ComponentDataVariable';
import { CollectionVariableType } from './data_collection/constants'; import { DataCollectionVariableType } from './data_collection/constants';
import DataCollectionVariable from './data_collection/DataCollectionVariable'; import DataCollectionVariable from './data_collection/DataCollectionVariable';
export interface DynamicVariableListenerManagerOptions { export interface DynamicVariableListenerManagerOptions {
@ -43,13 +43,13 @@ export default class DynamicVariableListenerManager {
const type = dynamicVariable.get('type'); const type = dynamicVariable.get('type');
let dataListeners: DataVariableListener[] = []; let dataListeners: DataVariableListener[] = [];
switch (type) { switch (type) {
case CollectionVariableType: case DataCollectionVariableType:
dataListeners = this.listenToDataCollectionVariable(dynamicVariable as DataCollectionVariable); dataListeners = this.listenToDataCollectionVariable(dynamicVariable as DataCollectionVariable);
break; break;
case DataVariableType: case DataVariableType:
dataListeners = this.listenToDataVariable(dynamicVariable as DataVariable | ComponentDataVariable, em); dataListeners = this.listenToDataVariable(dynamicVariable as DataVariable | ComponentDataVariable, em);
break; break;
case ConditionalVariableType: case DataConditionType:
dataListeners = this.listenToConditionalVariable(dynamicVariable as DataCondition, em); dataListeners = this.listenToConditionalVariable(dynamicVariable as DataCondition, em);
break; break;
} }

8
packages/core/src/data_sources/model/TraitDataVariable.ts

@ -1,14 +1,14 @@
import DataVariable, { DataVariableDefinition } from './DataVariable'; import DataVariable, { DataVariableProps } from './DataVariable';
import Trait from '../../trait_manager/model/Trait'; import Trait from '../../trait_manager/model/Trait';
import { TraitProperties } from '../../trait_manager/types'; import { TraitProperties } from '../../trait_manager/types';
export type TraitDataVariableDefinition = TraitProperties & DataVariableDefinition; export interface TraitDataVariableProps extends Omit<TraitProperties, 'type'>, DataVariableProps {}
export default class TraitDataVariable extends DataVariable { export default class TraitDataVariable extends DataVariable {
trait?: Trait; trait?: Trait;
constructor(attrs: TraitDataVariableDefinition, options: any) { constructor(props: TraitDataVariableProps, options: any) {
super(attrs, options); super(props, options);
this.trait = options.trait; this.trait = options.trait;
} }

23
packages/core/src/data_sources/model/conditional_variables/ConditionalComponent.ts → packages/core/src/data_sources/model/conditional_variables/ComponentDataCondition.ts

@ -1,30 +1,23 @@
import Component from '../../../dom_components/model/Component'; import Component from '../../../dom_components/model/Component';
import Components from '../../../dom_components/model/Components';
import { ComponentDefinition, ComponentOptions } from '../../../dom_components/model/types'; import { ComponentDefinition, ComponentOptions } from '../../../dom_components/model/types';
import { toLowerCase } from '../../../utils/mixins'; import { toLowerCase } from '../../../utils/mixins';
import { DataCondition, ConditionalVariableType, ExpressionDefinition, LogicGroupDefinition } from './DataCondition'; import { DataCondition, DataConditionProps, DataConditionType } from './DataCondition';
type ConditionalComponentDefinition = { export default class ComponentDataCondition extends Component {
condition: ExpressionDefinition | LogicGroupDefinition | boolean;
ifTrue: any;
ifFalse: any;
};
export default class ComponentConditionalVariable extends Component {
dataCondition: DataCondition; dataCondition: DataCondition;
componentDefinition: ConditionalComponentDefinition; componentDefinition: DataConditionProps;
constructor(componentDefinition: ConditionalComponentDefinition, opt: ComponentOptions) { constructor(props: DataConditionProps, opt: ComponentOptions) {
const { condition, ifTrue, ifFalse } = componentDefinition; const { condition, ifTrue, ifFalse } = props;
const dataConditionInstance = new DataCondition(condition, ifTrue, ifFalse, { em: opt.em }); const dataConditionInstance = new DataCondition(condition, ifTrue, ifFalse, { em: opt.em });
const initialComponentsProps = dataConditionInstance.getDataValue(); const initialComponentsProps = dataConditionInstance.getDataValue();
const conditionalCmptDef = { const conditionalCmptDef = {
type: ConditionalVariableType, type: DataConditionType,
components: initialComponentsProps, components: initialComponentsProps,
}; };
super(conditionalCmptDef, opt); super(conditionalCmptDef, opt);
this.componentDefinition = componentDefinition; this.componentDefinition = props;
this.dataCondition = dataConditionInstance; this.dataCondition = dataConditionInstance;
this.dataCondition.onValueChange = this.handleConditionChange.bind(this); this.dataCondition.onValueChange = this.handleConditionChange.bind(this);
} }
@ -37,7 +30,7 @@ export default class ComponentConditionalVariable extends Component {
} }
static isComponent(el: HTMLElement) { static isComponent(el: HTMLElement) {
return toLowerCase(el.tagName) === ConditionalVariableType; return toLowerCase(el.tagName) === DataConditionType;
} }
toJSON(): ComponentDefinition { toJSON(): ComponentDefinition {

24
packages/core/src/data_sources/model/conditional_variables/Condition.ts

@ -1,7 +1,7 @@
import { DataVariableDefinition, DataVariableType } from './../DataVariable'; import { DataVariableProps } from './../DataVariable';
import EditorModel from '../../../editor/model/Editor'; import EditorModel from '../../../editor/model/Editor';
import { evaluateVariable, isDataVariable } from '../utils'; import { evaluateVariable, isDataVariable } from '../utils';
import { ExpressionDefinition, LogicGroupDefinition } from './DataCondition'; import { ExpressionProps, LogicGroupProps } from './DataCondition';
import { LogicalGroupStatement } from './LogicalGroupStatement'; import { LogicalGroupStatement } from './LogicalGroupStatement';
import { Operator } from './operators'; import { Operator } from './operators';
import { GenericOperation, GenericOperator } from './operators/GenericOperator'; import { GenericOperation, GenericOperator } from './operators/GenericOperator';
@ -10,13 +10,15 @@ import { NumberOperator, NumberOperation } from './operators/NumberOperator';
import { StringOperator, StringOperation } from './operators/StringOperations'; import { StringOperator, StringOperation } from './operators/StringOperations';
import { Model } from '../../../common'; import { Model } from '../../../common';
export type ConditionProps = ExpressionProps | LogicGroupProps | boolean;
export class Condition extends Model { export class Condition extends Model {
private condition: ExpressionDefinition | LogicGroupDefinition | boolean; private condition: ConditionProps;
private em: EditorModel; private em: EditorModel;
constructor(condition: ExpressionDefinition | LogicGroupDefinition | boolean, opts: { em: EditorModel }) { constructor(props: ConditionProps, opts: { em: EditorModel }) {
super(condition); super(props);
this.condition = condition; this.condition = props;
this.em = opts.em; this.em = opts.em;
} }
@ -68,7 +70,7 @@ export class Condition extends Model {
* Extracts all data variables from the condition, including nested ones. * Extracts all data variables from the condition, including nested ones.
*/ */
getDataVariables() { getDataVariables() {
const variables: DataVariableDefinition[] = []; const variables: DataVariableProps[] = [];
this.extractVariables(this.condition, variables); this.extractVariables(this.condition, variables);
return variables; return variables;
} }
@ -77,8 +79,8 @@ export class Condition extends Model {
* Recursively extracts variables from expressions or logic groups. * Recursively extracts variables from expressions or logic groups.
*/ */
private extractVariables( private extractVariables(
condition: boolean | LogicGroupDefinition | ExpressionDefinition, condition: boolean | LogicGroupProps | ExpressionProps,
variables: DataVariableDefinition[], variables: DataVariableProps[],
): void { ): void {
if (this.isExpression(condition)) { if (this.isExpression(condition)) {
if (isDataVariable(condition.left)) variables.push(condition.left); if (isDataVariable(condition.left)) variables.push(condition.left);
@ -91,14 +93,14 @@ export class Condition extends Model {
/** /**
* Checks if a condition is a LogicGroup. * Checks if a condition is a LogicGroup.
*/ */
private isLogicGroup(condition: any): condition is LogicGroupDefinition { private isLogicGroup(condition: any): condition is LogicGroupProps {
return condition && typeof condition.logicalOperator !== 'undefined' && Array.isArray(condition.statements); return condition && typeof condition.logicalOperator !== 'undefined' && Array.isArray(condition.statements);
} }
/** /**
* Checks if a condition is an Expression. * Checks if a condition is an Expression.
*/ */
private isExpression(condition: any): condition is ExpressionDefinition { private isExpression(condition: any): condition is ExpressionProps {
return condition && typeof condition.left !== 'undefined' && typeof condition.operator === 'string'; return condition && typeof condition.left !== 'undefined' && typeof condition.operator === 'string';
} }

44
packages/core/src/data_sources/model/conditional_variables/DataCondition.ts

@ -5,37 +5,35 @@ import { Model } from '../../../common';
import { LogicalOperation } from './operators/LogicalOperator'; import { LogicalOperation } from './operators/LogicalOperator';
import DynamicVariableListenerManager from '../DataVariableListenerManager'; import DynamicVariableListenerManager from '../DataVariableListenerManager';
import EditorModel from '../../../editor/model/Editor'; import EditorModel from '../../../editor/model/Editor';
import { Condition } from './Condition'; import { Condition, ConditionProps } from './Condition';
import DataVariable, { DataVariableDefinition } from '../DataVariable'; import DataVariable, { DataVariableProps } from '../DataVariable';
import { evaluateVariable, isDataVariable } from '../utils'; import { evaluateVariable, isDataVariable } from '../utils';
export const ConditionalVariableType = 'conditional-variable'; export const DataConditionType = 'data-condition';
export type ExpressionDefinition = {
export interface ExpressionProps {
left: any; left: any;
operator: GenericOperation | StringOperation | NumberOperation; operator: GenericOperation | StringOperation | NumberOperation;
right: any; right: any;
}; }
export type LogicGroupDefinition = { export interface LogicGroupProps {
logicalOperator: LogicalOperation; logicalOperator: LogicalOperation;
statements: (ExpressionDefinition | LogicGroupDefinition | boolean)[]; statements: ConditionProps[];
}; }
export type ConditionDefinition = ExpressionDefinition | LogicGroupDefinition | boolean; export interface DataConditionProps {
export type ConditionalVariableDefinition = { type: typeof DataConditionType;
type: typeof ConditionalVariableType; condition: ConditionProps;
condition: ConditionDefinition;
ifTrue: any; ifTrue: any;
ifFalse: any; ifFalse: any;
}; }
type DataConditionType = { interface DataConditionPropsDefined extends Omit<DataConditionProps, 'condition'> {
type: typeof ConditionalVariableType;
condition: Condition; condition: Condition;
ifTrue: any; }
ifFalse: any;
}; export class DataCondition extends Model<DataConditionPropsDefined> {
export class DataCondition extends Model<DataConditionType> {
lastEvaluationResult: boolean; lastEvaluationResult: boolean;
private condition: Condition; private condition: Condition;
private em: EditorModel; private em: EditorModel;
@ -43,7 +41,7 @@ export class DataCondition extends Model<DataConditionType> {
private _onValueChange?: () => void; private _onValueChange?: () => void;
constructor( constructor(
condition: ExpressionDefinition | LogicGroupDefinition | boolean, condition: ConditionProps,
public ifTrue: any, public ifTrue: any,
public ifFalse: any, public ifFalse: any,
opts: { em: EditorModel; onValueChange?: () => void }, opts: { em: EditorModel; onValueChange?: () => void },
@ -54,7 +52,7 @@ export class DataCondition extends Model<DataConditionType> {
const conditionInstance = new Condition(condition, { em: opts.em }); const conditionInstance = new Condition(condition, { em: opts.em });
super({ super({
type: ConditionalVariableType, type: DataConditionType,
condition: conditionInstance, condition: conditionInstance,
ifTrue, ifTrue,
ifFalse, ifFalse,
@ -107,7 +105,7 @@ export class DataCondition extends Model<DataConditionType> {
} }
getDependentDataVariables() { getDependentDataVariables() {
const dataVariables: DataVariableDefinition[] = this.condition.getDataVariables(); const dataVariables: DataVariableProps[] = this.condition.getDataVariables();
if (isDataVariable(this.ifTrue)) dataVariables.push(this.ifTrue); if (isDataVariable(this.ifTrue)) dataVariables.push(this.ifTrue);
if (isDataVariable(this.ifFalse)) dataVariables.push(this.ifFalse); if (isDataVariable(this.ifFalse)) dataVariables.push(this.ifFalse);
@ -121,7 +119,7 @@ export class DataCondition extends Model<DataConditionType> {
toJSON() { toJSON() {
return { return {
type: ConditionalVariableType, type: DataConditionType,
condition: this.condition, condition: this.condition,
ifTrue: this.ifTrue, ifTrue: this.ifTrue,
ifFalse: this.ifFalse, ifFalse: this.ifFalse,

7
packages/core/src/data_sources/model/conditional_variables/LogicalGroupStatement.ts

@ -1,14 +1,13 @@
import { LogicalOperator } from './operators/LogicalOperator';
import { ExpressionDefinition, LogicGroupDefinition } from './DataCondition';
import { Condition } from './Condition';
import EditorModel from '../../../editor/model/Editor'; import EditorModel from '../../../editor/model/Editor';
import { Condition, ConditionProps } from './Condition';
import { LogicalOperator } from './operators/LogicalOperator';
export class LogicalGroupStatement { export class LogicalGroupStatement {
private em: EditorModel; private em: EditorModel;
constructor( constructor(
private operator: LogicalOperator, private operator: LogicalOperator,
private statements: (ExpressionDefinition | LogicGroupDefinition | boolean)[], private statements: ConditionProps[],
opts: { em: EditorModel }, opts: { em: EditorModel },
) { ) {
this.em = opts.em; this.em = opts.em;

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

@ -1,28 +1,23 @@
import DataVariable, { DataVariableType } from '../DataVariable';
import { isArray } from 'underscore'; import { isArray } from 'underscore';
import { ObjectAny } from '../../../common';
import Component from '../../../dom_components/model/Component'; import Component from '../../../dom_components/model/Component';
import { ComponentDefinition, ComponentDefinitionDefined, ComponentOptions } from '../../../dom_components/model/types'; import { ComponentDefinition, ComponentDefinitionDefined, ComponentOptions } from '../../../dom_components/model/types';
import EditorModel from '../../../editor/model/Editor';
import { toLowerCase } from '../../../utils/mixins'; import { toLowerCase } from '../../../utils/mixins';
import DataSource from '../DataSource'; import DataSource from '../DataSource';
import { ObjectAny } from '../../../common'; import DataVariable, { DataVariableType } from '../DataVariable';
import EditorModel from '../../../editor/model/Editor'; import DynamicVariableListenerManager from '../DataVariableListenerManager';
import { DataCollectionType, keyCollectionDefinition, keyCollectionsStateMap, keyIsCollectionItem } from './constants';
import { import {
ComponentDataCollectionDefinition, ComponentDataCollectionProps,
DataCollectionConfig, DataCollectionConfig,
DataCollectionDefinition, DataCollectionProps,
DataCollectionState, DataCollectionState,
DataCollectionStateMap, DataCollectionStateMap,
} from './types'; } from './types';
import {
keyCollectionDefinition,
keyCollectionsStateMap,
CollectionComponentType,
keyIsCollectionItem,
} from './constants';
import DynamicVariableListenerManager from '../DataVariableListenerManager';
export default class ComponentDataCollection extends Component { export default class ComponentDataCollection extends Component {
constructor(props: ComponentDataCollectionDefinition, opt: ComponentOptions) { constructor(props: ComponentDataCollectionProps, opt: ComponentOptions) {
const collectionDef = props[keyCollectionDefinition]; const collectionDef = props[keyCollectionDefinition];
if (opt.forCloning) { if (opt.forCloning) {
// If we are cloning, leave setting the collection items to the main symbol collection // If we are cloning, leave setting the collection items to the main symbol collection
@ -58,7 +53,7 @@ export default class ComponentDataCollection extends Component {
} }
static isComponent(el: HTMLElement) { static isComponent(el: HTMLElement) {
return toLowerCase(el.tagName) === CollectionComponentType; return toLowerCase(el.tagName) === DataCollectionType;
} }
hasDynamicDataSource() { hasDynamicDataSource() {
@ -67,7 +62,7 @@ export default class ComponentDataCollection extends Component {
} }
toJSON(opts?: ObjectAny) { toJSON(opts?: ObjectAny) {
const json = super.toJSON.call(this, opts) as ComponentDataCollectionDefinition; const json = super.toJSON.call(this, opts) as ComponentDataCollectionProps;
json[keyCollectionDefinition].componentDef = this.getComponentDef(); json[keyCollectionDefinition].componentDef = this.getComponentDef();
delete json.components; delete json.components;
@ -127,7 +122,7 @@ export default class ComponentDataCollection extends Component {
function getCollectionItems( function getCollectionItems(
em: EditorModel, em: EditorModel,
collectionDef: DataCollectionDefinition, collectionDef: DataCollectionProps,
parentCollectionStateMap: DataCollectionStateMap, parentCollectionStateMap: DataCollectionStateMap,
opt: ComponentOptions, opt: ComponentOptions,
) { ) {

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

@ -1,9 +1,9 @@
import Component from '../../../dom_components/model/Component'; import Component from '../../../dom_components/model/Component';
import { ComponentOptions, ComponentProperties } from '../../../dom_components/model/types'; import { ComponentOptions } from '../../../dom_components/model/types';
import { toLowerCase } from '../../../utils/mixins'; import { toLowerCase } from '../../../utils/mixins';
import DataCollectionVariable from './DataCollectionVariable'; import DataCollectionVariable from './DataCollectionVariable';
import { CollectionVariableType, keyCollectionsStateMap } from './constants'; import { DataCollectionVariableType, keyCollectionsStateMap } from './constants';
import { DataCollectionStateMap, DataCollectionVariableDefinition } from './types'; import { ComponentDataCollectionVariableProps, DataCollectionStateMap } from './types';
export default class ComponentDataCollectionVariable extends Component { export default class ComponentDataCollectionVariable extends Component {
datacollectionVariable: DataCollectionVariable; datacollectionVariable: DataCollectionVariable;
@ -14,14 +14,14 @@ export default class ComponentDataCollectionVariable extends Component {
return { return {
...componentDefaults, ...componentDefaults,
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: undefined, collectionId: undefined,
variableType: undefined, variableType: undefined,
path: undefined, path: undefined,
}; };
} }
constructor(props: DataCollectionVariableDefinition & ComponentProperties, opt: ComponentOptions) { constructor(props: ComponentDataCollectionVariableProps, opt: ComponentOptions) {
super(props, opt); super(props, opt);
const em = opt.em; const em = opt.em;
const { type, variableType, path, collectionId } = props; const { type, variableType, path, collectionId } = props;
@ -50,6 +50,6 @@ export default class ComponentDataCollectionVariable extends Component {
} }
static isComponent(el: HTMLElement) { static isComponent(el: HTMLElement) {
return toLowerCase(el.tagName) === CollectionVariableType; return toLowerCase(el.tagName) === DataCollectionVariableType;
} }
} }

23
packages/core/src/data_sources/model/data_collection/DataCollectionVariable.ts

@ -1,23 +1,24 @@
import { DataCollectionVariableDefinition } from './types'; import { DataCollectionVariableProps } 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 { CollectionVariableType } from './constants'; import { DataCollectionVariableType } from './constants';
import { DataCollectionState, DataCollectionStateMap } from './types'; import { DataCollectionState, DataCollectionStateMap } from './types';
import DynamicVariableListenerManager from '../DataVariableListenerManager'; import DynamicVariableListenerManager from '../DataVariableListenerManager';
type ResolvedDataCollectionVariable = DataCollectionVariableDefinition & {
interface DataCollectionVariablePropsDefined extends DataCollectionVariableProps {
value?: any; value?: any;
}; }
export default class DataCollectionVariable extends Model<ResolvedDataCollectionVariable> { export default class DataCollectionVariable extends Model<DataCollectionVariablePropsDefined> {
em: EditorModel; em: EditorModel;
collectionsStateMap?: DataCollectionStateMap; collectionsStateMap?: DataCollectionStateMap;
dataVariable?: DataVariable; dataVariable?: DataVariable;
dynamicValueListener?: DynamicVariableListenerManager; dynamicValueListener?: DynamicVariableListenerManager;
defaults(): Partial<ResolvedDataCollectionVariable> { defaults(): Partial<DataCollectionVariablePropsDefined> {
return { return {
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: undefined, collectionId: undefined,
variableType: undefined, variableType: undefined,
path: undefined, path: undefined,
@ -26,13 +27,13 @@ export default class DataCollectionVariable extends Model<ResolvedDataCollection
} }
constructor( constructor(
attrs: ResolvedDataCollectionVariable, props: DataCollectionVariablePropsDefined,
options: { options: {
em: EditorModel; em: EditorModel;
collectionsStateMap?: DataCollectionStateMap; collectionsStateMap?: DataCollectionStateMap;
}, },
) { ) {
super(attrs, options); super(props, options);
this.em = options.em; this.em = options.em;
this.collectionsStateMap = options.collectionsStateMap; this.collectionsStateMap = options.collectionsStateMap;
this.updateDataVariable(); this.updateDataVariable();
@ -56,7 +57,7 @@ export default class DataCollectionVariable extends Model<ResolvedDataCollection
if (!this.collectionsStateMap) return { resolvedValue: undefined }; if (!this.collectionsStateMap) return { resolvedValue: undefined };
const resolvedValue = resolveCollectionVariable( const resolvedValue = resolveCollectionVariable(
this.attributes as DataCollectionVariableDefinition, this.attributes as DataCollectionVariableProps,
this.collectionsStateMap, this.collectionsStateMap,
this.em, this.em,
); );
@ -102,7 +103,7 @@ export default class DataCollectionVariable extends Model<ResolvedDataCollection
} }
function resolveCollectionVariable( function resolveCollectionVariable(
collectionVariableDefinition: DataCollectionVariableDefinition, collectionVariableDefinition: DataCollectionVariableProps,
collectionsStateMap: DataCollectionStateMap, collectionsStateMap: DataCollectionStateMap,
em: EditorModel, em: EditorModel,
) { ) {

4
packages/core/src/data_sources/model/data_collection/constants.ts

@ -1,5 +1,5 @@
export const CollectionComponentType = 'collection-component'; export const DataCollectionType = 'data-collection';
export const DataCollectionVariableType = 'data-collection-variable';
export const keyCollectionDefinition = 'collectionDef'; export const keyCollectionDefinition = 'collectionDef';
export const keyIsCollectionItem = '__is_data_collection_item'; export const keyIsCollectionItem = '__is_data_collection_item';
export const CollectionVariableType = 'parent-collection-variable';
export const keyCollectionsStateMap = '__collections_state_map'; export const keyCollectionsStateMap = '__collections_state_map';

26
packages/core/src/data_sources/model/data_collection/types.ts

@ -1,8 +1,8 @@
import { CollectionComponentType, CollectionVariableType, keyCollectionDefinition } from './constants'; import { DataCollectionType, DataCollectionVariableType, keyCollectionDefinition } from './constants';
import { ComponentDefinition } from '../../../dom_components/model/types'; import { ComponentDefinition, ComponentProperties } from '../../../dom_components/model/types';
import { DataVariableDefinition } from '../DataVariable'; import { DataVariableProps } from '../DataVariable';
export type DataCollectionDataSource = any[] | DataVariableDefinition | DataCollectionVariableDefinition; export type DataCollectionDataSource = any[] | DataVariableProps | DataCollectionVariableProps;
export interface DataCollectionConfig { export interface DataCollectionConfig {
collectionId: string; collectionId: string;
@ -35,19 +35,23 @@ export interface DataCollectionStateMap {
[key: string]: DataCollectionState; [key: string]: DataCollectionState;
} }
export interface ComponentDataCollectionDefinition extends ComponentDefinition { export interface ComponentDataCollectionProps extends ComponentDefinition {
[keyCollectionDefinition]: DataCollectionDefinition; [keyCollectionDefinition]: DataCollectionProps;
} }
export interface DataCollectionDefinition { export interface ComponentDataCollectionVariableProps
type: typeof CollectionComponentType; extends DataCollectionVariableProps,
Omit<ComponentProperties, 'type'> {}
export interface DataCollectionProps {
type: typeof DataCollectionType;
collectionConfig: DataCollectionConfig; collectionConfig: DataCollectionConfig;
componentDef: ComponentDefinition; componentDef: ComponentDefinition;
} }
export type DataCollectionVariableDefinition = { export interface DataCollectionVariableProps {
type: typeof CollectionVariableType; type: typeof DataCollectionVariableType;
variableType: DataCollectionStateVariableType; variableType: DataCollectionStateVariableType;
collectionId: string; collectionId: string;
path?: string; path?: string;
}; }

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

@ -1,15 +1,14 @@
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import { DynamicValue, DynamicValueDefinition } from '../types'; import { DynamicValue, DynamicValueProps } from '../types';
import { DataCollectionStateMap } from './data_collection/types'; import { DataCollectionStateMap } from './data_collection/types';
import DataCollectionVariable from './data_collection/DataCollectionVariable'; import DataCollectionVariable from './data_collection/DataCollectionVariable';
import { CollectionVariableType } from './data_collection/constants'; import { DataCollectionVariableType } from './data_collection/constants';
import { ConditionalVariableType, DataCondition } from './conditional_variables/DataCondition'; import { DataConditionType, DataCondition } from './conditional_variables/DataCondition';
import DataVariable, { DataVariableType } from './DataVariable'; import DataVariable, { DataVariableType } from './DataVariable';
export function isDynamicValueDefinition(value: any): value is DynamicValueDefinition { export function isDynamicValueDefinition(value: any): value is DynamicValueProps {
return ( return (
typeof value === 'object' && typeof value === 'object' && [DataVariableType, DataConditionType, DataCollectionVariableType].includes(value?.type)
[DataVariableType, ConditionalVariableType, CollectionVariableType].includes(value?.type)
); );
} }
@ -22,7 +21,7 @@ export function isDataVariable(variable: any) {
} }
export function isDataCondition(variable: any) { export function isDataCondition(variable: any) {
return variable?.type === ConditionalVariableType; return variable?.type === DataConditionType;
} }
export function evaluateVariable(variable: any, em: EditorModel) { export function evaluateVariable(variable: any, em: EditorModel) {
@ -30,7 +29,7 @@ export function evaluateVariable(variable: any, em: EditorModel) {
} }
export function getDynamicValueInstance( export function getDynamicValueInstance(
valueDefinition: DynamicValueDefinition, valueDefinition: DynamicValueProps,
options: { options: {
em: EditorModel; em: EditorModel;
collectionsStateMap?: DataCollectionStateMap; collectionsStateMap?: DataCollectionStateMap;
@ -44,12 +43,12 @@ export function getDynamicValueInstance(
case DataVariableType: case DataVariableType:
dynamicVariable = new DataVariable(valueDefinition, { em: em }); dynamicVariable = new DataVariable(valueDefinition, { em: em });
break; break;
case ConditionalVariableType: { case DataConditionType: {
const { condition, ifTrue, ifFalse } = valueDefinition; const { condition, ifTrue, ifFalse } = valueDefinition;
dynamicVariable = new DataCondition(condition, ifTrue, ifFalse, { em: em }); dynamicVariable = new DataCondition(condition, ifTrue, ifFalse, { em: em });
break; break;
} }
case CollectionVariableType: { case DataCollectionVariableType: {
dynamicVariable = new DataCollectionVariable(valueDefinition, options); dynamicVariable = new DataCollectionVariable(valueDefinition, options);
break; break;
} }
@ -61,7 +60,7 @@ export function getDynamicValueInstance(
} }
export function evaluateDynamicValueDefinition( export function evaluateDynamicValueDefinition(
valueDefinition: DynamicValueDefinition, valueDefinition: DynamicValueProps,
options: { options: {
em: EditorModel; em: EditorModel;
collectionsStateMap?: DataCollectionStateMap; collectionsStateMap?: DataCollectionStateMap;

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

@ -1,17 +1,16 @@
import { ObjectAny } from '../common'; import { ObjectAny } from '../common';
import DataCollectionVariable from './model/data_collection/DataCollectionVariable'; import DataCollectionVariable from './model/data_collection/DataCollectionVariable';
import { DataCollectionVariableDefinition } from './model/data_collection/types'; import { DataCollectionVariableProps } 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';
import DataRecords from './model/DataRecords'; import DataRecords from './model/DataRecords';
import DataVariable, { DataVariableDefinition } from './model/DataVariable'; import DataVariable, { DataVariableProps } from './model/DataVariable';
import { ConditionalVariableDefinition, DataCondition } from './model/conditional_variables/DataCondition'; import { DataConditionProps, DataCondition } from './model/conditional_variables/DataCondition';
export type DynamicValue = DataVariable | ComponentDataVariable | DataCondition | DataCollectionVariable; export type DynamicValue = DataVariable | ComponentDataVariable | DataCondition | DataCollectionVariable;
export type DynamicValueDefinition =
| DataVariableDefinition export type DynamicValueProps = DataVariableProps | DataConditionProps | DataCollectionVariableProps;
| ConditionalVariableDefinition
| DataCollectionVariableDefinition;
export interface DataRecordProps extends ObjectAny { export interface DataRecordProps extends ObjectAny {
/** /**
* Record id. * Record id.

4
packages/core/src/data_sources/view/ComponentDataConditionView.ts

@ -0,0 +1,4 @@
import ComponentView from '../../dom_components/view/ComponentView';
import ComponentDataCondition from '../model/conditional_variables/ComponentDataCondition';
export default class ComponentDataConditionView extends ComponentView<ComponentDataCondition> {}

4
packages/core/src/data_sources/view/ComponentDynamicView.ts

@ -1,4 +0,0 @@
import ComponentView from '../../dom_components/view/ComponentView';
import ConditionalComponent from '../model/conditional_variables/ConditionalComponent';
export default class ConditionalComponentView extends ComponentView<ConditionalComponent> {}

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

@ -125,12 +125,12 @@ import { BlockProperties } from '../block_manager/model/Block';
import ComponentDataVariable from '../data_sources/model/ComponentDataVariable'; import ComponentDataVariable from '../data_sources/model/ComponentDataVariable';
import ComponentDataVariableView from '../data_sources/view/ComponentDataVariableView'; import ComponentDataVariableView from '../data_sources/view/ComponentDataVariableView';
import { DataVariableType } from '../data_sources/model/DataVariable'; import { DataVariableType } from '../data_sources/model/DataVariable';
import { ConditionalVariableType } from '../data_sources/model/conditional_variables/DataCondition'; import { DataConditionType } from '../data_sources/model/conditional_variables/DataCondition';
import ComponentConditionalVariable from '../data_sources/model/conditional_variables/ConditionalComponent'; import ComponentDataCondition from '../data_sources/model/conditional_variables/ComponentDataCondition';
import ConditionalComponentView from '../data_sources/view/ComponentDynamicView'; import ComponentDataConditionView from '../data_sources/view/ComponentDataConditionView';
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, CollectionVariableType } from '../data_sources/model/data_collection/constants'; import { DataCollectionType, DataCollectionVariableType } from '../data_sources/model/data_collection/constants';
import ComponentDataCollectionVariable from '../data_sources/model/data_collection/ComponentDataCollectionVariable'; import ComponentDataCollectionVariable from '../data_sources/model/data_collection/ComponentDataCollectionVariable';
import ComponentDataCollectionVariableView from '../data_sources/model/data_collection/ComponentDataCollectionVariableView'; import ComponentDataCollectionVariableView from '../data_sources/model/data_collection/ComponentDataCollectionVariableView';
@ -199,19 +199,19 @@ 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, id: DataCollectionVariableType,
model: ComponentDataCollectionVariable, model: ComponentDataCollectionVariable,
view: ComponentDataCollectionVariableView, view: ComponentDataCollectionVariableView,
}, },
{ {
id: CollectionComponentType, id: DataCollectionType,
model: ComponentDataCollection, model: ComponentDataCollection,
view: ComponentDataCollectionView, view: ComponentDataCollectionView,
}, },
{ {
id: ConditionalVariableType, id: DataConditionType,
model: ComponentConditionalVariable, model: ComponentDataCondition,
view: ConditionalComponentView, view: ComponentDataConditionView,
}, },
{ {
id: DataVariableType, id: DataVariableType,

6
packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts

@ -1,5 +1,5 @@
import { Model, ObjectAny } from '../../common'; import { Model, ObjectAny } from '../../common';
import { CollectionVariableType, keyIsCollectionItem } from '../../data_sources/model/data_collection/constants'; import { DataCollectionVariableType, keyIsCollectionItem } from '../../data_sources/model/data_collection/constants';
import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types'; import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import Component from './Component'; import Component from './Component';
@ -82,8 +82,8 @@ export class ComponentDynamicValueWatcher extends Model<Component> {
private updateSymbolOverride() { private updateSymbolOverride() {
if (!this.component || !this.component.get(keyIsCollectionItem)) return; if (!this.component || !this.component.get(keyIsCollectionItem)) return;
const keys = this.propertyWatcher.getDynamicValuesOfType(CollectionVariableType); const keys = this.propertyWatcher.getDynamicValuesOfType(DataCollectionVariableType);
const attributesKeys = this.attributeWatcher.getDynamicValuesOfType(CollectionVariableType); const attributesKeys = this.attributeWatcher.getDynamicValuesOfType(DataCollectionVariableType);
const combinedKeys = [keyCollectionsStateMap, ...keys]; const combinedKeys = [keyCollectionsStateMap, ...keys];
const haveOverridenAttributes = Object.keys(attributesKeys).length; const haveOverridenAttributes = Object.keys(attributesKeys).length;

10
packages/core/src/dom_components/model/DynamicValueWatcher.ts

@ -1,11 +1,11 @@
import { DynamicValueDefinition } from './../../data_sources/types'; import { DynamicValueProps } from './../../data_sources/types';
import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types'; import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types';
import { Model, ObjectAny } from '../../common'; import { Model, ObjectAny } from '../../common';
import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager'; import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import { evaluateDynamicValueDefinition, isDynamicValueDefinition } from '../../data_sources/model/utils'; import { evaluateDynamicValueDefinition, isDynamicValueDefinition } from '../../data_sources/model/utils';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import Component from './Component'; import Component from './Component';
import { CollectionVariableType } from '../../data_sources/model/data_collection/constants'; import { DataCollectionVariableType } from '../../data_sources/model/data_collection/constants';
import { ModelDestroyOptions } from 'backbone'; import { ModelDestroyOptions } from 'backbone';
export interface DynamicWatchersOptions { export interface DynamicWatchersOptions {
@ -39,9 +39,9 @@ export class DynamicValueWatcher extends Model<{ component: Component | undefine
updateCollectionStateMap(collectionsStateMap: DataCollectionStateMap) { updateCollectionStateMap(collectionsStateMap: DataCollectionStateMap) {
this.collectionsStateMap = collectionsStateMap; this.collectionsStateMap = collectionsStateMap;
const collectionVariablesKeys = this.getDynamicValuesOfType(CollectionVariableType); const collectionVariablesKeys = this.getDynamicValuesOfType(DataCollectionVariableType);
const collectionVariablesObject = collectionVariablesKeys.reduce( const collectionVariablesObject = collectionVariablesKeys.reduce(
(acc: { [key: string]: DynamicValueDefinition | null }, key) => { (acc: { [key: string]: DynamicValueProps | null }, key) => {
acc[key] = null; acc[key] = null;
return acc; return acc;
}, },
@ -163,7 +163,7 @@ export class DynamicValueWatcher extends Model<{ component: Component | undefine
return serializableValues; return serializableValues;
} }
getDynamicValuesOfType(type: DynamicValueDefinition['type']) { getDynamicValuesOfType(type: DynamicValueProps['type']) {
const keys = Object.keys(this.dynamicVariableListeners).filter((key: string) => { const keys = Object.keys(this.dynamicVariableListeners).filter((key: string) => {
// @ts-ignore // @ts-ignore
return this.dynamicVariableListeners[key].dynamicVariable.get('type') === type; return this.dynamicVariableListeners[key].dynamicVariable.get('type') === type;

9
packages/core/src/dom_components/model/SymbolUtils.ts

@ -3,7 +3,10 @@ import Component, { keySymbol, keySymbolOvrd, keySymbols } from './Component';
import { SymbolToUpOptions } from './types'; import { SymbolToUpOptions } from './types';
import { isEmptyObj } from '../../utils/mixins'; import { isEmptyObj } from '../../utils/mixins';
import Components from './Components'; import Components from './Components';
import { CollectionVariableType, keyCollectionDefinition } from '../../data_sources/model/data_collection/constants'; import {
DataCollectionVariableType,
keyCollectionDefinition,
} from '../../data_sources/model/data_collection/constants';
export const isSymbolMain = (cmp: Component) => isArray(cmp.get(keySymbols)); export const isSymbolMain = (cmp: Component) => isArray(cmp.get(keySymbols));
@ -175,10 +178,10 @@ const shouldPropagateProperty = (props: Record<string, any>, prop: string, compo
const isCollectionVariableDefinition = (() => { const isCollectionVariableDefinition = (() => {
if (prop === 'attributes') { if (prop === 'attributes') {
const attributes = props['attributes']; const attributes = props['attributes'];
return Object.values(attributes).some((attr: any) => attr?.type === CollectionVariableType); return Object.values(attributes).some((attr: any) => attr?.type === DataCollectionVariableType);
} }
return props[prop]?.type === CollectionVariableType; return props[prop]?.type === DataCollectionVariableType;
})(); })();
return !isSymbolOverride(component, prop) || isCollectionVariableDefinition; return !isSymbolOverride(component, prop) || isCollectionVariableDefinition;

18
packages/core/src/domain_abstract/model/StyleableModel.ts

@ -1,23 +1,23 @@
import { isArray, isString, keys } from 'underscore'; import { isArray, isString, keys } from 'underscore';
import { Model, ObjectAny, ObjectHash, SetOptions, View } from '../../common'; import { Model, ObjectAny, ObjectHash, SetOptions } from '../../common';
import ParserHtml from '../../parser/model/ParserHtml'; import ParserHtml from '../../parser/model/ParserHtml';
import Selectors from '../../selector_manager/model/Selectors'; import Selectors from '../../selector_manager/model/Selectors';
import { shallowDiff } from '../../utils/mixins'; import { shallowDiff } from '../../utils/mixins';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import StyleDataVariable from '../../data_sources/model/StyleDataVariable'; import StyleDataVariable from '../../data_sources/model/StyleDataVariable';
import { DataVariableDefinition, DataVariableType } from '../../data_sources/model/DataVariable'; import { DataVariableProps, DataVariableType } from '../../data_sources/model/DataVariable';
import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager'; import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import CssRuleView from '../../css_composer/view/CssRuleView'; import CssRuleView from '../../css_composer/view/CssRuleView';
import ComponentView from '../../dom_components/view/ComponentView'; import ComponentView from '../../dom_components/view/ComponentView';
import Frame from '../../canvas/model/Frame'; import Frame from '../../canvas/model/Frame';
import { import {
DataCondition, DataCondition,
ConditionalVariableType, DataConditionType,
ConditionalVariableDefinition, DataConditionProps,
} from '../../data_sources/model/conditional_variables/DataCondition'; } from '../../data_sources/model/conditional_variables/DataCondition';
import { isDynamicValue, isDynamicValueDefinition } from '../../data_sources/model/utils'; import { isDynamicValue, isDynamicValueDefinition } from '../../data_sources/model/utils';
import { DynamicValueDefinition } from '../../data_sources/types'; import { DynamicValueProps } from '../../data_sources/types';
export type StyleProps = Record<string, string | string[] | DataVariableDefinition | ConditionalVariableDefinition>; export type StyleProps = Record<string, string | string[] | DataVariableProps | DataConditionProps>;
export type UpdateStyleOptions = SetOptions & { export type UpdateStyleOptions = SetOptions & {
partial?: boolean; partial?: boolean;
@ -139,21 +139,21 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
return newStyle; return newStyle;
} }
private resolveDynamicValue(styleValue: DynamicValueDefinition) { private resolveDynamicValue(styleValue: DynamicValueProps) {
const dynamicType = styleValue.type; const dynamicType = styleValue.type;
let styleDynamicVariable; let styleDynamicVariable;
switch (dynamicType) { switch (dynamicType) {
case DataVariableType: case DataVariableType:
styleDynamicVariable = new StyleDataVariable(styleValue, { em: this.em }); styleDynamicVariable = new StyleDataVariable(styleValue, { em: this.em });
break; break;
case ConditionalVariableType: { case DataConditionType: {
const { condition, ifTrue, ifFalse } = styleValue; const { condition, ifTrue, ifFalse } = styleValue;
styleDynamicVariable = new DataCondition(condition, ifTrue, ifFalse, { em: this.em! }); styleDynamicVariable = new DataCondition(condition, ifTrue, ifFalse, { em: this.em! });
break; break;
} }
default: default:
throw new Error( throw new Error(
`Unsupported dynamic value type for styles. Only '${DataVariableType}' and '${ConditionalVariableType}' are supported. Received '${dynamicType}'.`, `Unsupported dynamic value type for styles. Only '${DataVariableType}' and '${DataConditionType}' are supported. Received '${dynamicType}'.`,
); );
} }

2
packages/core/src/trait_manager/model/Trait.ts

@ -1,4 +1,4 @@
import { ConditionalVariableType, DataCondition } from './../../data_sources/model/conditional_variables/DataCondition'; import { DataCondition } from './../../data_sources/model/conditional_variables/DataCondition';
import { isString, isUndefined } from 'underscore'; import { isString, isUndefined } from 'underscore';
import Category from '../../abstract/ModuleCategory'; import Category from '../../abstract/ModuleCategory';
import { LocaleOptions, Model, SetOptions } from '../../common'; import { LocaleOptions, Model, SetOptions } from '../../common';

31
packages/core/test/specs/data_sources/model/conditional_variables/ComponentConditionalVariable.ts

@ -1,11 +1,12 @@
import { Component, DataSourceManager, Editor } from '../../../../../src'; import { Component, DataSourceManager, Editor } from '../../../../../src';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import { MissingConditionError } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; import {
import { ConditionalVariableType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; MissingConditionError,
DataConditionType,
} from '../../../../../src/data_sources/model/conditional_variables/DataCondition';
import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator'; import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator';
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator';
import { DataSourceProps } from '../../../../../src/data_sources/types'; import ComponentDataConditionView from '../../../../../src/data_sources/view/ComponentDataConditionView';
import ConditionalComponentView from '../../../../../src/data_sources/view/ComponentDynamicView';
import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper';
import ComponentTableView from '../../../../../src/dom_components/view/ComponentTableView'; import ComponentTableView from '../../../../../src/dom_components/view/ComponentTableView';
import ComponentTextView from '../../../../../src/dom_components/view/ComponentTextView'; import ComponentTextView from '../../../../../src/dom_components/view/ComponentTextView';
@ -28,7 +29,7 @@ describe('ComponentConditionalVariable', () => {
it('should add a component with a condition that evaluates a component definition', () => { it('should add a component with a condition that evaluates a component definition', () => {
const component = cmpRoot.append({ const component = cmpRoot.append({
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -41,10 +42,10 @@ describe('ComponentConditionalVariable', () => {
}, },
})[0]; })[0];
expect(component).toBeDefined(); expect(component).toBeDefined();
expect(component.get('type')).toBe(ConditionalVariableType); expect(component.get('type')).toBe(DataConditionType);
expect(component.getInnerHTML()).toBe('<h1>some text</h1>'); expect(component.getInnerHTML()).toBe('<h1>some text</h1>');
const componentView = component.getView(); const componentView = component.getView();
expect(componentView).toBeInstanceOf(ConditionalComponentView); expect(componentView).toBeInstanceOf(ComponentDataConditionView);
expect(componentView?.el.textContent).toBe('some text'); expect(componentView?.el.textContent).toBe('some text');
const childComponent = getFirstChild(component); const childComponent = getFirstChild(component);
@ -58,7 +59,7 @@ describe('ComponentConditionalVariable', () => {
it('should add a component with a condition that evaluates a string', () => { it('should add a component with a condition that evaluates a string', () => {
const component = cmpRoot.append({ const component = cmpRoot.append({
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -67,10 +68,10 @@ describe('ComponentConditionalVariable', () => {
ifTrue: '<h1>some text</h1>', ifTrue: '<h1>some text</h1>',
})[0]; })[0];
expect(component).toBeDefined(); expect(component).toBeDefined();
expect(component.get('type')).toBe(ConditionalVariableType); expect(component.get('type')).toBe(DataConditionType);
expect(component.getInnerHTML()).toBe('<h1>some text</h1>'); expect(component.getInnerHTML()).toBe('<h1>some text</h1>');
const componentView = component.getView(); const componentView = component.getView();
expect(componentView).toBeInstanceOf(ConditionalComponentView); expect(componentView).toBeInstanceOf(ComponentDataConditionView);
expect(componentView?.el.textContent).toBe('some text'); expect(componentView?.el.textContent).toBe('some text');
const childComponent = getFirstChild(component); const childComponent = getFirstChild(component);
@ -93,7 +94,7 @@ describe('ComponentConditionalVariable', () => {
dsm.add(dataSource); dsm.add(dataSource);
const component = cmpRoot.append({ const component = cmpRoot.append({
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: { left: {
type: DataVariableType, type: DataVariableType,
@ -142,7 +143,7 @@ describe('ComponentConditionalVariable', () => {
dsm.add(dataSource); dsm.add(dataSource);
const component = cmpRoot.append({ const component = cmpRoot.append({
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: { left: {
type: DataVariableType, type: DataVariableType,
@ -158,7 +159,7 @@ describe('ComponentConditionalVariable', () => {
tagName: 'div', tagName: 'div',
components: [ components: [
{ {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: { left: {
type: DataVariableType, type: DataVariableType,
@ -189,7 +190,7 @@ describe('ComponentConditionalVariable', () => {
it('should store conditional components', () => { it('should store conditional components', () => {
const conditionalCmptDef = { const conditionalCmptDef = {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -215,7 +216,7 @@ describe('ComponentConditionalVariable', () => {
it('should throw an error if no condition is passed', () => { it('should throw an error if no condition is passed', () => {
const conditionalCmptDef = { const conditionalCmptDef = {
type: ConditionalVariableType, type: DataConditionType,
ifTrue: { ifTrue: {
tagName: 'h1', tagName: 'h1',
type: 'text', type: 'text',

11
packages/core/test/specs/data_sources/model/conditional_variables/ConditionalStyles.ts

@ -1,12 +1,11 @@
import { DataSourceManager, Editor } from '../../../../../src'; import { DataSourceManager, Editor } from '../../../../../src';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import { import {
ConditionalVariableType, DataConditionType,
MissingConditionError, MissingConditionError,
} from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; } from '../../../../../src/data_sources/model/conditional_variables/DataCondition';
import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator'; import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator';
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator';
import { DataSourceProps } from '../../../../../src/data_sources/types';
import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper';
import EditorModel from '../../../../../src/editor/model/Editor'; import EditorModel from '../../../../../src/editor/model/Editor';
import { filterObjectForSnapshot, setupTestEditor } from '../../../../common'; import { filterObjectForSnapshot, setupTestEditor } from '../../../../common';
@ -32,7 +31,7 @@ describe('StyleConditionalVariable', () => {
content: 'some text', content: 'some text',
style: { style: {
color: { color: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -64,7 +63,7 @@ describe('StyleConditionalVariable', () => {
content: 'some text', content: 'some text',
style: { style: {
color: { color: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: { left: {
type: DataVariableType, type: DataVariableType,
@ -96,7 +95,7 @@ describe('StyleConditionalVariable', () => {
content: 'some text', content: 'some text',
style: { style: {
color: { color: {
type: ConditionalVariableType, type: DataConditionType,
ifTrue: 'grey', ifTrue: 'grey',
ifFalse: 'red', ifFalse: 'red',
}, },
@ -112,7 +111,7 @@ describe('StyleConditionalVariable', () => {
content: 'some text', content: 'some text',
style: { style: {
color: { color: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,

10
packages/core/test/specs/data_sources/model/conditional_variables/ConditionalTraits.ts

@ -1,5 +1,5 @@
import { DataSourceManager, Editor } from '../../../../../src'; import { DataSourceManager, Editor } from '../../../../../src';
import { ConditionalVariableType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; import { DataConditionType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition';
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator';
import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper';
import EditorModel from '../../../../../src/editor/model/Editor'; import EditorModel from '../../../../../src/editor/model/Editor';
@ -34,7 +34,7 @@ describe('conditional traits', () => {
label: 'Value', label: 'Value',
name: 'value', name: 'value',
value: { value: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -68,7 +68,7 @@ describe('conditional traits', () => {
name: 'value', name: 'value',
changeProp: true, changeProp: true,
value: { value: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -103,7 +103,7 @@ describe('conditional traits', () => {
name: 'value', name: 'value',
changeProp: true, changeProp: true,
value: { value: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
@ -138,7 +138,7 @@ describe('conditional traits', () => {
name: 'value', name: 'value',
changeProp: true, changeProp: true,
value: { value: {
type: ConditionalVariableType, type: DataConditionType,
condition: { condition: {
left: 0, left: 0,
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,

39
packages/core/test/specs/data_sources/model/conditional_variables/DataCondition.ts

@ -1,15 +1,14 @@
import { DataSourceManager } from '../../../../../src'; import { DataSourceManager } from '../../../../../src';
import { import {
DataCondition, DataCondition,
ExpressionDefinition, ExpressionProps,
LogicGroupDefinition, LogicGroupProps,
} from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; } from '../../../../../src/data_sources/model/conditional_variables/DataCondition';
import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator'; import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator';
import { LogicalOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/LogicalOperator'; import { LogicalOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/LogicalOperator';
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator';
import { StringOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/StringOperations'; import { StringOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/StringOperations';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import { DataSourceProps } from '../../../../../src/data_sources/types';
import Editor from '../../../../../src/editor/model/Editor'; import Editor from '../../../../../src/editor/model/Editor';
import EditorModel from '../../../../../src/editor/model/Editor'; import EditorModel from '../../../../../src/editor/model/Editor';
@ -52,14 +51,14 @@ describe('DataCondition', () => {
describe('Operator Tests', () => { describe('Operator Tests', () => {
test('should evaluate using GenericOperation operators', () => { test('should evaluate using GenericOperation operators', () => {
const condition: ExpressionDefinition = { left: 5, operator: GenericOperation.equals, right: 5 }; const condition: ExpressionProps = { left: 5, operator: GenericOperation.equals, right: 5 };
const dataCondition = new DataCondition(condition, 'Equal', 'Not Equal', { em }); const dataCondition = new DataCondition(condition, 'Equal', 'Not Equal', { em });
expect(dataCondition.getDataValue()).toBe('Equal'); expect(dataCondition.getDataValue()).toBe('Equal');
}); });
test('equals (false)', () => { test('equals (false)', () => {
const condition: ExpressionDefinition = { const condition: ExpressionProps = {
left: 'hello', left: 'hello',
operator: GenericOperation.equals, operator: GenericOperation.equals,
right: 'world', right: 'world',
@ -69,21 +68,21 @@ describe('DataCondition', () => {
}); });
test('should evaluate using StringOperation operators', () => { test('should evaluate using StringOperation operators', () => {
const condition: ExpressionDefinition = { left: 'apple', operator: StringOperation.contains, right: 'app' }; const condition: ExpressionProps = { left: 'apple', operator: StringOperation.contains, right: 'app' };
const dataCondition = new DataCondition(condition, 'Contains', "Doesn't contain", { em }); const dataCondition = new DataCondition(condition, 'Contains', "Doesn't contain", { em });
expect(dataCondition.getDataValue()).toBe('Contains'); expect(dataCondition.getDataValue()).toBe('Contains');
}); });
test('should evaluate using NumberOperation operators', () => { test('should evaluate using NumberOperation operators', () => {
const condition: ExpressionDefinition = { left: 10, operator: NumberOperation.lessThan, right: 15 }; const condition: ExpressionProps = { left: 10, operator: NumberOperation.lessThan, right: 15 };
const dataCondition = new DataCondition(condition, 'Valid', 'Invalid', { em }); const dataCondition = new DataCondition(condition, 'Valid', 'Invalid', { em });
expect(dataCondition.getDataValue()).toBe('Valid'); expect(dataCondition.getDataValue()).toBe('Valid');
}); });
test('should evaluate using LogicalOperation operators', () => { test('should evaluate using LogicalOperation operators', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.and, logicalOperator: LogicalOperation.and,
statements: [ statements: [
{ left: true, operator: GenericOperation.equals, right: true }, { left: true, operator: GenericOperation.equals, right: true },
@ -103,7 +102,7 @@ describe('DataCondition', () => {
}); });
test('should evaluate complex nested conditions', () => { test('should evaluate complex nested conditions', () => {
const nestedLogicGroup: LogicGroupDefinition = { const nestedLogicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.or, logicalOperator: LogicalOperation.or,
statements: [ statements: [
{ {
@ -124,7 +123,7 @@ describe('DataCondition', () => {
describe('LogicalGroup Tests', () => { describe('LogicalGroup Tests', () => {
test('should correctly handle AND logical operator', () => { test('should correctly handle AND logical operator', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.and, logicalOperator: LogicalOperation.and,
statements: [ statements: [
{ left: true, operator: GenericOperation.equals, right: true }, { left: true, operator: GenericOperation.equals, right: true },
@ -137,7 +136,7 @@ describe('DataCondition', () => {
}); });
test('should correctly handle OR logical operator', () => { test('should correctly handle OR logical operator', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.or, logicalOperator: LogicalOperation.or,
statements: [ statements: [
{ left: true, operator: GenericOperation.equals, right: false }, { left: true, operator: GenericOperation.equals, right: false },
@ -150,7 +149,7 @@ describe('DataCondition', () => {
}); });
test('should correctly handle XOR logical operator', () => { test('should correctly handle XOR logical operator', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.xor, logicalOperator: LogicalOperation.xor,
statements: [ statements: [
{ left: true, operator: GenericOperation.equals, right: true }, { left: true, operator: GenericOperation.equals, right: true },
@ -164,7 +163,7 @@ describe('DataCondition', () => {
}); });
test('should handle nested logical groups', () => { test('should handle nested logical groups', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.and, logicalOperator: LogicalOperation.and,
statements: [ statements: [
{ left: true, operator: GenericOperation.equals, right: true }, { left: true, operator: GenericOperation.equals, right: true },
@ -183,7 +182,7 @@ describe('DataCondition', () => {
}); });
test('should handle groups with false conditions', () => { test('should handle groups with false conditions', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.and, logicalOperator: LogicalOperation.and,
statements: [ statements: [
{ left: true, operator: GenericOperation.equals, right: true }, { left: true, operator: GenericOperation.equals, right: true },
@ -199,7 +198,7 @@ describe('DataCondition', () => {
describe('Conditions with dataVariables', () => { describe('Conditions with dataVariables', () => {
test('should return "Yes" when dataVariable matches expected value', () => { test('should return "Yes" when dataVariable matches expected value', () => {
const condition: ExpressionDefinition = { const condition: ExpressionProps = {
left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.USER_1.status' }, left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.USER_1.status' },
operator: GenericOperation.equals, operator: GenericOperation.equals,
right: 'active', right: 'active',
@ -210,7 +209,7 @@ describe('DataCondition', () => {
}); });
test('should return "No" when dataVariable does not match expected value', () => { test('should return "No" when dataVariable does not match expected value', () => {
const condition: ExpressionDefinition = { const condition: ExpressionProps = {
left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.USER_1.status' }, left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.USER_1.status' },
operator: GenericOperation.equals, operator: GenericOperation.equals,
right: 'inactive', right: 'inactive',
@ -222,7 +221,7 @@ describe('DataCondition', () => {
// TODO: unskip after adding UndefinedOperator // TODO: unskip after adding UndefinedOperator
test.skip('should handle missing data variable gracefully', () => { test.skip('should handle missing data variable gracefully', () => {
const condition: ExpressionDefinition = { const condition: ExpressionProps = {
left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.not_a_user.status' }, left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.not_a_user.status' },
operator: GenericOperation.isDefined, operator: GenericOperation.isDefined,
right: undefined, right: undefined,
@ -233,7 +232,7 @@ describe('DataCondition', () => {
}); });
test('should correctly compare numeric values from dataVariables', () => { test('should correctly compare numeric values from dataVariables', () => {
const condition: ExpressionDefinition = { const condition: ExpressionProps = {
left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.USER_1.age' }, left: { type: DataVariableType, path: 'USER_STATUS_SOURCE.USER_1.age' },
operator: NumberOperation.greaterThan, operator: NumberOperation.greaterThan,
right: 24, right: 24,
@ -249,7 +248,7 @@ describe('DataCondition', () => {
}; };
dsm.add(dataSource2); dsm.add(dataSource2);
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.and, logicalOperator: LogicalOperation.and,
statements: [ statements: [
{ {
@ -270,7 +269,7 @@ describe('DataCondition', () => {
}); });
test('should handle nested logical conditions with data variables', () => { test('should handle nested logical conditions with data variables', () => {
const logicGroup: LogicGroupDefinition = { const logicGroup: LogicGroupProps = {
logicalOperator: LogicalOperation.or, logicalOperator: LogicalOperation.or,
statements: [ statements: [
{ {

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

@ -1,8 +1,8 @@
import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src'; import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import { import {
CollectionComponentType, DataCollectionType,
CollectionVariableType, DataCollectionVariableType,
} 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';
@ -41,7 +41,7 @@ describe('Collection component', () => {
test('Collection component should be undroppable', () => { test('Collection component should be undroppable', () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -61,7 +61,7 @@ describe('Collection component', () => {
test('Collection items should be undraggable', () => { test('Collection items should be undraggable', () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -83,7 +83,7 @@ describe('Collection component', () => {
test('Collection items should be symbols', () => { test('Collection items should be symbols', () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -138,7 +138,7 @@ describe('Collection component', () => {
beforeEach(() => { beforeEach(() => {
cmp = wrapper.components({ cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -146,7 +146,7 @@ describe('Collection component', () => {
{ {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -154,20 +154,20 @@ describe('Collection component', () => {
}, },
{ {
tagName: 'span', tagName: 'span',
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: 'currentItem', variableType: 'currentItem',
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'firstName', path: 'firstName',
}, },
], ],
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
}, },
custom_property: { custom_property: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -280,7 +280,7 @@ describe('Collection component', () => {
test('Updating the value to a different collection variable', async () => { test('Updating the value to a different collection variable', async () => {
firstChild.set('name', { firstChild.set('name', {
// @ts-ignore // @ts-ignore
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'age', path: 'age',
@ -299,7 +299,7 @@ describe('Collection component', () => {
firstGrandchild.set('name', { firstGrandchild.set('name', {
// @ts-ignore // @ts-ignore
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'age', path: 'age',
@ -354,7 +354,7 @@ describe('Collection component', () => {
beforeEach(() => { beforeEach(() => {
cmp = wrapper.components({ cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -363,7 +363,7 @@ describe('Collection component', () => {
type: 'default', type: 'default',
attributes: { attributes: {
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -373,7 +373,7 @@ describe('Collection component', () => {
], ],
attributes: { attributes: {
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -446,7 +446,7 @@ describe('Collection component', () => {
firstChild.setAttributes({ firstChild.setAttributes({
name: { name: {
// @ts-ignore // @ts-ignore
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'age', path: 'age',
@ -471,7 +471,7 @@ describe('Collection component', () => {
firstGrandchild.setAttributes({ firstGrandchild.setAttributes({
name: { name: {
// @ts-ignore // @ts-ignore
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'age', path: 'age',
@ -533,7 +533,7 @@ describe('Collection component', () => {
test('Traits', () => { test('Traits', () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -541,7 +541,7 @@ describe('Collection component', () => {
{ {
name: 'attribute_trait', name: 'attribute_trait',
value: { value: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -551,7 +551,7 @@ describe('Collection component', () => {
name: 'property_trait', name: 'property_trait',
changeProp: true, changeProp: true,
value: { value: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -599,20 +599,20 @@ describe('Collection component', () => {
const cmpDefinition = { const cmpDefinition = {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
}, },
custom_prop: { custom_prop: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentIndex, variableType: DataCollectionStateVariableType.currentIndex,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
}, },
attributes: { attributes: {
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -622,7 +622,7 @@ describe('Collection component', () => {
{ {
name: 'attribute_trait', name: 'attribute_trait',
value: { value: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -632,7 +632,7 @@ describe('Collection component', () => {
name: 'property_trait', name: 'property_trait',
changeProp: true, changeProp: true,
value: { value: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -642,7 +642,7 @@ describe('Collection component', () => {
}; };
const collectionComponentDefinition = { const collectionComponentDefinition = {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
...cmpDefinition, ...cmpDefinition,
@ -670,7 +670,7 @@ describe('Collection component', () => {
const newChildDefinition = { const newChildDefinition = {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentIndex, variableType: DataCollectionStateVariableType.currentIndex,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -692,7 +692,7 @@ describe('Collection component', () => {
const newChildDefinition = { const newChildDefinition = {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentIndex, variableType: DataCollectionStateVariableType.currentIndex,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -717,12 +717,12 @@ describe('Collection component', () => {
attributes: { attributes: {
attribute_trait: { attribute_trait: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
name: { name: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
@ -732,32 +732,32 @@ describe('Collection component', () => {
attributes: { attributes: {
attribute_trait: { attribute_trait: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
name: { name: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
}, },
name: { name: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
custom_prop: { custom_prop: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: 'currentIndex', variableType: 'currentIndex',
}, },
property_trait: { property_trait: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
@ -767,32 +767,32 @@ describe('Collection component', () => {
attributes: { attributes: {
attribute_trait: { attribute_trait: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
name: { name: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
}, },
name: { name: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
custom_prop: { custom_prop: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: 'currentIndex', variableType: 'currentIndex',
}, },
property_trait: { property_trait: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
@ -801,19 +801,19 @@ describe('Collection component', () => {
], ],
name: { name: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
custom_prop: { custom_prop: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: 'currentIndex', variableType: 'currentIndex',
}, },
property_trait: { property_trait: {
path: 'user', path: 'user',
type: CollectionVariableType, type: DataCollectionVariableType,
collectionId: 'my_collection', collectionId: 'my_collection',
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
}, },
@ -829,7 +829,7 @@ describe('Collection component', () => {
startIndex: 0, startIndex: 0,
}, },
}, },
type: 'collection-component', type: DataCollectionType,
}, },
], ],
docEl: { docEl: {
@ -895,12 +895,12 @@ describe('Collection component', () => {
describe('Configuration options', () => { describe('Configuration options', () => {
test('Collection with start and end indexes', () => { test('Collection with start and end indexes', () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -943,18 +943,18 @@ describe('Collection component', () => {
stateVariableTests.forEach(({ variableType, expectedValues }) => { stateVariableTests.forEach(({ variableType, expectedValues }) => {
test(`Variable type: ${variableType}`, () => { test(`Variable type: ${variableType}`, () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: variableType, variableType: variableType,
collectionId: 'my_collection', collectionId: 'my_collection',
}, },
attributes: { attributes: {
custom_attribute: { custom_attribute: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: variableType, variableType: variableType,
collectionId: 'my_collection', collectionId: 'my_collection',
}, },
@ -963,7 +963,7 @@ describe('Collection component', () => {
{ {
name: 'attribute_trait', name: 'attribute_trait',
value: { value: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: variableType, variableType: variableType,
collectionId: 'my_collection', collectionId: 'my_collection',
}, },
@ -972,7 +972,7 @@ describe('Collection component', () => {
name: 'property_trait', name: 'property_trait',
changeProp: true, changeProp: true,
value: { value: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: variableType, variableType: variableType,
collectionId: 'my_collection', collectionId: 'my_collection',
}, },

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

@ -1,8 +1,8 @@
import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src'; import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import { import {
CollectionComponentType, DataCollectionType,
CollectionVariableType, DataCollectionVariableType,
} 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';
@ -40,13 +40,13 @@ describe('Collection variable components', () => {
test('Gets the correct static value', async () => { test('Gets the correct static value', async () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
components: [ components: [
{ {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -74,12 +74,12 @@ describe('Collection variable components', () => {
test('Watches collection variable changes', async () => { test('Watches collection variable changes', async () => {
const cmp = wrapper.components({ const cmp = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
components: { components: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -110,14 +110,14 @@ describe('Collection variable components', () => {
beforeEach(() => { beforeEach(() => {
const variableCmpDef = { const variableCmpDef = {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
}; };
const collectionComponentDefinition = { const collectionComponentDefinition = {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
@ -148,7 +148,7 @@ describe('Collection variable components', () => {
const firstChild = cmp.components().at(0); const firstChild = cmp.components().at(0);
const newChildDefinition = { const newChildDefinition = {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentIndex, variableType: DataCollectionStateVariableType.currentIndex,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -167,7 +167,7 @@ describe('Collection variable components', () => {
const firstChild = cmp.components().at(0); const firstChild = cmp.components().at(0);
const newChildDefinition = { const newChildDefinition = {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentIndex, variableType: DataCollectionStateVariableType.currentIndex,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -192,7 +192,7 @@ describe('Collection variable components', () => {
type: 'default', type: 'default',
components: [ components: [
{ {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'my_collection', collectionId: 'my_collection',
path: 'user', path: 'user',
@ -209,7 +209,7 @@ describe('Collection variable components', () => {
startIndex: 0, startIndex: 0,
}, },
}, },
type: 'collection-component', type: DataCollectionType,
}, },
], ],
docEl: { docEl: {

132
packages/core/test/specs/data_sources/model/data_collection/__snapshots__/ComponentDataCollection.ts.snap

@ -17,13 +17,13 @@ exports[`Collection component Serialization Saving: Collection with grandchildre
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
@ -33,13 +33,13 @@ exports[`Collection component Serialization Saving: Collection with grandchildre
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
@ -48,7 +48,7 @@ exports[`Collection component Serialization Saving: Collection with grandchildre
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"type": "default", "type": "default",
@ -57,19 +57,19 @@ exports[`Collection component Serialization Saving: Collection with grandchildre
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -79,32 +79,32 @@ exports[`Collection component Serialization Saving: Collection with grandchildre
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -113,25 +113,25 @@ exports[`Collection component Serialization Saving: Collection with grandchildre
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;
@ -152,13 +152,13 @@ exports[`Collection component Serialization Saving: Collection with no grandchil
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
@ -168,32 +168,32 @@ exports[`Collection component Serialization Saving: Collection with no grandchil
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -203,32 +203,32 @@ exports[`Collection component Serialization Saving: Collection with no grandchil
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -237,25 +237,25 @@ exports[`Collection component Serialization Saving: Collection with no grandchil
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;
@ -276,13 +276,13 @@ exports[`Collection component Serialization Serializion with Collection Variable
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
@ -292,13 +292,13 @@ exports[`Collection component Serialization Serializion with Collection Variable
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
@ -307,7 +307,7 @@ exports[`Collection component Serialization Serializion with Collection Variable
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"type": "default", "type": "default",
@ -316,19 +316,19 @@ exports[`Collection component Serialization Serializion with Collection Variable
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -338,32 +338,32 @@ exports[`Collection component Serialization Serializion with Collection Variable
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -372,25 +372,25 @@ exports[`Collection component Serialization Serializion with Collection Variable
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;
@ -411,13 +411,13 @@ exports[`Collection component Serialization Serializion with Collection Variable
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
@ -427,32 +427,32 @@ exports[`Collection component Serialization Serializion with Collection Variable
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -462,32 +462,32 @@ exports[`Collection component Serialization Serializion with Collection Variable
"attribute_trait": { "attribute_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
}, },
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
@ -496,24 +496,24 @@ exports[`Collection component Serialization Serializion with Collection Variable
"custom_prop": { "custom_prop": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
"name": { "name": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"property_trait": { "property_trait": {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;

20
packages/core/test/specs/data_sources/model/data_collection/__snapshots__/ComponentDataCollectionVariable.ts.snap

@ -20,14 +20,14 @@ exports[`Collection variable components Serialization Saving: Collection with co
{ {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
], ],
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;
@ -50,7 +50,7 @@ exports[`Collection variable components Serialization Saving: Collection with co
{ {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
], ],
@ -59,14 +59,14 @@ exports[`Collection variable components Serialization Saving: Collection with co
{ {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
], ],
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;
@ -90,14 +90,14 @@ exports[`Collection variable components Serialization Serializion to JSON: Colle
{ {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
], ],
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;
@ -120,7 +120,7 @@ exports[`Collection variable components Serialization Serializion to JSON: Colle
{ {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentIndex", "variableType": "currentIndex",
}, },
], ],
@ -129,13 +129,13 @@ exports[`Collection variable components Serialization Serializion to JSON: Colle
{ {
"collectionId": "my_collection", "collectionId": "my_collection",
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
], ],
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;

6
packages/core/test/specs/data_sources/model/data_collection/__snapshots__/nestedComponentDataCollections.ts.snap

@ -22,15 +22,15 @@ exports[`Collection component Nested collections are correctly serialized 1`] =
"componentDef": { "componentDef": {
"name": { "name": {
"path": "user", "path": "user",
"type": "parent-collection-variable", "type": "data-collection-variable",
"variableType": "currentItem", "variableType": "currentItem",
}, },
"type": "default", "type": "default",
}, },
}, },
"type": "collection-component", "type": "data-collection",
}, },
}, },
"type": "collection-component", "type": "data-collection",
} }
`; `;

50
packages/core/test/specs/data_sources/model/data_collection/nestedComponentDataCollections.ts

@ -1,8 +1,8 @@
import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src'; import { Component, DataRecord, DataSource, DataSourceManager, Editor } from '../../../../../src';
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable';
import { import {
CollectionComponentType, DataCollectionType,
CollectionVariableType, DataCollectionVariableType,
} 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';
@ -52,15 +52,15 @@ describe('Collection component', () => {
test('Nested collections bind to correct data sources', () => { test('Nested collections bind to correct data sources', () => {
const parentCollection = wrapper.components({ const parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'nested_collection', collectionId: 'nested_collection',
path: 'user', path: 'user',
@ -95,15 +95,15 @@ describe('Collection component', () => {
test('Updates in parent collection propagate to nested collections', () => { test('Updates in parent collection propagate to nested collections', () => {
const parentCollection = wrapper.components({ const parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'nested_collection', collectionId: 'nested_collection',
path: 'user', path: 'user',
@ -139,15 +139,15 @@ describe('Collection component', () => {
test('Nested collections are correctly serialized', () => { test('Nested collections are correctly serialized', () => {
const parentCollection = wrapper.components({ const parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
path: 'user', path: 'user',
}, },
@ -177,15 +177,15 @@ describe('Collection component', () => {
test('Nested collections respect startIndex and endIndex', () => { test('Nested collections respect startIndex and endIndex', () => {
const parentCollection = wrapper.components({ const parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'nested_collection', collectionId: 'nested_collection',
path: 'user', path: 'user',
@ -218,15 +218,15 @@ describe('Collection component', () => {
test('Nested collection gets and watches value from the parent collection', () => { test('Nested collection gets and watches value from the parent collection', () => {
const parentCollection = wrapper.components({ const parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'parent_collection', collectionId: 'parent_collection',
path: 'user', path: 'user',
@ -264,15 +264,15 @@ describe('Collection component', () => {
test('Nested collection switches to using its own collection variable', () => { test('Nested collection switches to using its own collection variable', () => {
const parentCollection = wrapper.components({ const parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
path: 'user', path: 'user',
collectionId: 'parent_collection', collectionId: 'parent_collection',
@ -303,7 +303,7 @@ describe('Collection component', () => {
// Replace the collection variable with one from the inner collection // Replace the collection variable with one from the inner collection
firstChild.set('name', { firstChild.set('name', {
// @ts-ignore // @ts-ignore
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
path: 'user', path: 'user',
collectionId: 'nested_collection', collectionId: 'nested_collection',
@ -319,12 +319,12 @@ describe('Collection component', () => {
beforeEach(() => { beforeEach(() => {
// Initialize the parent and nested collections // Initialize the parent and nested collections
parentCollection = wrapper.components({ parentCollection = wrapper.components({
type: CollectionComponentType, type: DataCollectionType,
collectionDef: { collectionDef: {
componentDef: { componentDef: {
type: CollectionComponentType, type: DataCollectionType,
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'parent_collection', collectionId: 'parent_collection',
path: 'user', path: 'user',
@ -333,7 +333,7 @@ describe('Collection component', () => {
componentDef: { componentDef: {
type: 'default', type: 'default',
name: { name: {
type: CollectionVariableType, type: DataCollectionVariableType,
variableType: DataCollectionStateVariableType.currentItem, variableType: DataCollectionStateVariableType.currentItem,
collectionId: 'nested_collection', collectionId: 'nested_collection',
path: 'user', path: 'user',

Loading…
Cancel
Save