mirror of https://github.com/artf/grapesjs.git
Browse Source
* Avoid throwing errors if no condition is passed to a DataCondition * Refactor Condition class * Remove expecting errors for conditions tests * Extend and refactor BaseOperator * Rename and refactor GenericOperator * Rename and refactor logicalOperator to BooleanOperator * Refactor StringOperator * Refactor NumberOperator * Refactor and fix DataResolverListener * Update tests for condition Operators * Rename Condition class to ConditionEvaluator * Add missing types file * Update and refactor DataCondition * Update utils * Refactor StyleableModel class * Update ComponentDataCondition * Refactor ComponentResolverWatcher * Fix conditional styles * Rename LogicalGroupStatement to LogicalGroupEvaluator * Fix tests for DataCondition * Add setter methods for component data variable * Add setters and getter to ComponentDataCondition * Add getters to ComponentDataVariable * Rename test file * Make dynamic components undroppable * Fix collection types * Update collections ( add setters and getter, first item editable, sync styles ) * Update data collection tests * Format tests * Fix some ComponentData collection bugs * Refactor setStartIndex and setEndIndex * Fix getComponentDef test * Fix bug with end index = 0 * fix test for setDataSource * fix test for HTML updates * Format * Add tests for the new option in getDataValue for conditions ( skipDynamicValueResolution ) * rename Operation to DataConditionOperation * Run __onStyleChange after style changes as before * Format * Up BooleanOperator * Avoid raising errors for wrong dynamic value types * Refactor DataCondition * Format * Refactor how component data variable works internally * Symbols fix * Add docs * Refactor componentDatacondition * Add types for Datacondition output ( result ) types * Refactor DataCondition * Refactor ComponentDataCollection * Refactor styleableModel * Add missing files and utils * Up tests for ComponentDataCondition * Add new tests for component data condition * Fix quality check * Move ComponentDataVariable path and default value to dataResolver property * Update component data condition structure * Refactor data condition * Fix ifTrue and ifFalse position in ComponentDataCondition * Fix typescript * Change setIfTrueContent to be setIfTrueComponents * Fix memory leak for binding to this.postRender * Cleanup ComponentDataConditionView * Up tests * Save ComponentDataVariable on dataResolverChange * Remove DataCollection componentDef * Add setCollectionId method * Replace DataCollectionVariable with DataVariable * cleanup * Fix bug * PR review * Add new API endpoints * Add getCollectionsStateMap to ComponentDataVariable * Fix tests * up DataSources * Merge branch 'dev' of https://github.com/GrapesJS/grapesjs into dynamic-values-improvements * Push branch with refactored datasources * Fix conditions nested inside collections * Refactor how collectionsStateMap works * Add DataVariable static methods * Fix dataconditions nested inside collections * format * Remove collectionsStateMap on component drag * Fix remainingItems state * Make the first component item as the main symbol * make layrable as false * Update how datacollection components sync styles --------- Co-authored-by: Artur Arseniev <artur.catch@hotmail.it>pull/6498/head
committed by
GitHub
27 changed files with 895 additions and 675 deletions
@ -0,0 +1,93 @@ |
|||
import { ModelDestroyOptions } from 'backbone'; |
|||
import { ObjectAny } from '../../common'; |
|||
import Component from '../../dom_components/model/Component'; |
|||
import { DataResolver, DataResolverProps, ResolverFromProps } from '../types'; |
|||
import { ComponentOptions, ComponentProperties } from '../../dom_components/model/types'; |
|||
import { DataCollectionStateMap } from './data_collection/types'; |
|||
|
|||
interface ComponentWithDataResolverProps<T extends DataResolverProps> extends ComponentProperties { |
|||
type: T['type']; |
|||
dataResolver: T; |
|||
} |
|||
|
|||
export abstract class ComponentWithDataResolver<T extends DataResolverProps> extends Component { |
|||
dataResolver: ResolverFromProps<T>; |
|||
|
|||
constructor(props: ComponentWithDataResolverProps<T>, opt: ComponentOptions) { |
|||
super(props, opt); |
|||
|
|||
this.dataResolver = this.initializeDataResolver(props, opt); |
|||
this.listenToPropsChange(); |
|||
} |
|||
|
|||
private initializeDataResolver( |
|||
props: ComponentWithDataResolverProps<T>, |
|||
opt: ComponentOptions, |
|||
): ResolverFromProps<T> { |
|||
const resolverProps = props.dataResolver ?? { |
|||
type: props.type, |
|||
}; |
|||
|
|||
const resolver = this.createResolverInstance(resolverProps, { |
|||
...opt, |
|||
collectionsStateMap: this.collectionsStateMap, |
|||
}); |
|||
|
|||
return resolver as ResolverFromProps<T>; |
|||
} |
|||
|
|||
protected abstract createResolverInstance( |
|||
props: T, |
|||
options: ComponentOptions & { collectionsStateMap: DataCollectionStateMap }, |
|||
): DataResolver; |
|||
|
|||
getDataResolver() { |
|||
return this.get('dataResolver'); |
|||
} |
|||
|
|||
setDataResolver(props: any) { |
|||
return this.set('dataResolver', props); |
|||
} |
|||
|
|||
onCollectionsStateMapUpdate(collectionsStateMap: DataCollectionStateMap): void { |
|||
this.dataResolver.updateCollectionsStateMap(collectionsStateMap); |
|||
super.onCollectionsStateMapUpdate(collectionsStateMap); |
|||
} |
|||
|
|||
protected listenToPropsChange() { |
|||
this.listenTo( |
|||
this.dataResolver, |
|||
'change', |
|||
(() => { |
|||
this.__changesUp({ m: this }); |
|||
}).bind(this), |
|||
); |
|||
|
|||
this.on('change:dataResolver', () => { |
|||
// @ts-ignore
|
|||
this.dataResolver.set(this.get('dataResolver')); |
|||
}); |
|||
} |
|||
|
|||
protected removePropsListeners() { |
|||
this.stopListening(this.dataResolver); |
|||
this.off('change:dataResolver'); |
|||
this.off(`change:${this.collectionsStateMap}`); |
|||
} |
|||
|
|||
destroy(options?: ModelDestroyOptions | undefined): false | JQueryXHR { |
|||
this.removePropsListeners(); |
|||
return super.destroy(options); |
|||
} |
|||
|
|||
toJSON(opts?: ObjectAny): any { |
|||
const json = super.toJSON(opts); |
|||
const dataResolver = this.dataResolver.toJSON(); |
|||
delete dataResolver.type; |
|||
|
|||
return { |
|||
...json, |
|||
dataResolver, |
|||
}; |
|||
} |
|||
} |
|||
@ -1,23 +1,21 @@ |
|||
import EditorModel from '../../../editor/model/Editor'; |
|||
import { DataCollectionStateMap } from '../data_collection/types'; |
|||
import { DataConditionEvaluator, ConditionProps } from './DataConditionEvaluator'; |
|||
import { BooleanOperator } from './operators/BooleanOperator'; |
|||
|
|||
export class LogicalGroupEvaluator { |
|||
private em: EditorModel; |
|||
|
|||
constructor( |
|||
private operator: BooleanOperator, |
|||
private statements: ConditionProps[], |
|||
opts: { em: EditorModel }, |
|||
) { |
|||
this.em = opts.em; |
|||
} |
|||
private opts: { em: EditorModel; collectionsStateMap: DataCollectionStateMap }, |
|||
) {} |
|||
|
|||
evaluate(): boolean { |
|||
const results = this.statements.map((statement) => { |
|||
const condition = new DataConditionEvaluator({ condition: statement }, { em: this.em }); |
|||
const condition = new DataConditionEvaluator({ condition: statement }, this.opts); |
|||
return condition.evaluate(); |
|||
}); |
|||
|
|||
return this.operator.evaluate(results); |
|||
} |
|||
} |
|||
|
|||
@ -1,14 +1,20 @@ |
|||
import EditorModel from '../../../../editor/model/Editor'; |
|||
import { DataConditionOperation } from './types'; |
|||
import { enumToArray } from '../../../utils'; |
|||
import { DataConditionSimpleOperation } from '../types'; |
|||
|
|||
export abstract class Operator<OperationType extends DataConditionOperation> { |
|||
export abstract class SimpleOperator<OperationType extends DataConditionSimpleOperation> { |
|||
protected em: EditorModel; |
|||
protected operation: OperationType; |
|||
protected operationString: OperationType; |
|||
protected abstract operationsEnum: Record<string, OperationType>; |
|||
|
|||
constructor(operation: any, opts: { em: EditorModel }) { |
|||
this.operation = operation; |
|||
constructor(operationString: any, opts: { em: EditorModel }) { |
|||
this.operationString = operationString; |
|||
this.em = opts.em; |
|||
} |
|||
|
|||
abstract evaluate(left: any, right: any): boolean; |
|||
|
|||
getOperations(): DataConditionSimpleOperation[] { |
|||
return enumToArray(this.operationsEnum); |
|||
} |
|||
} |
|||
|
|||
@ -1,6 +0,0 @@ |
|||
import { AnyTypeOperation } from './AnyTypeOperator'; |
|||
import { BooleanOperation } from './BooleanOperator'; |
|||
import { NumberOperation } from './NumberOperator'; |
|||
import { StringOperation } from './StringOperator'; |
|||
|
|||
export type DataConditionOperation = AnyTypeOperation | StringOperation | NumberOperation | BooleanOperation; |
|||
@ -0,0 +1,7 @@ |
|||
import { AnyTypeOperation } from './operators/AnyTypeOperator'; |
|||
import { BooleanOperation } from './operators/BooleanOperator'; |
|||
import { NumberOperation } from './operators/NumberOperator'; |
|||
import { StringOperation } from './operators/StringOperator'; |
|||
|
|||
export type DataConditionSimpleOperation = AnyTypeOperation | StringOperation | NumberOperation | BooleanOperation; |
|||
export type DataConditionCompositeOperation = DataConditionSimpleOperation; |
|||
Loading…
Reference in new issue