Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor data variable listeners to a generic dynamic variable #6229

Merged
merged 2 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/core/src/css_composer/model/CssRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { isEmptyObj, hasWin } from '../../utils/mixins';
import Selector, { SelectorProps } from '../../selector_manager/model/Selector';
import EditorModel from '../../editor/model/Editor';
import CssRuleView from '../view/CssRuleView';
import DataVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';

/** @private */
export interface CssRuleProperties {
Expand Down Expand Up @@ -95,7 +95,7 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
em?: EditorModel;
opt: any;
views: CssRuleView[] = [];
dataVariableListeners: Record<string, DataVariableListenerManager> = {};
dynamicVariableListeners: Record<string, DynamicVariableListenerManager> = {};

defaults() {
return {
Expand Down
50 changes: 30 additions & 20 deletions packages/core/src/data_sources/model/DataVariableListenerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,59 @@ import { DataSourcesEvents, DataVariableListener } from '../types';
import { stringToPath } from '../../utils/mixins';
import { Model } from '../../common';
import EditorModel from '../../editor/model/Editor';
import DataVariable from './DataVariable';
import DataVariable, { DataVariableType } from './DataVariable';
import ComponentView from '../../dom_components/view/ComponentView';
import ComponentDataVariable from './ComponentDataVariable';

export interface DataVariableListenerManagerOptions {
export interface DynamicVariableListenerManagerOptions {
model: Model | ComponentView;
em: EditorModel;
dataVariable: DataVariable | ComponentDataVariable;
updateValueFromDataVariable: (value: any) => void;
}

export default class DataVariableListenerManager {
export default class DynamicVariableListenerManager {
private dataListeners: DataVariableListener[] = [];
private em: EditorModel;
private model: Model | ComponentView;
private dataVariable: DataVariable | ComponentDataVariable;
private updateValueFromDataVariable: (value: any) => void;
private dynamicVariable: DataVariable | ComponentDataVariable;
private updateValueFromDynamicVariable: (value: any) => void;

constructor(options: DataVariableListenerManagerOptions) {
constructor(options: DynamicVariableListenerManagerOptions) {
this.em = options.em;
this.model = options.model;
this.dataVariable = options.dataVariable;
this.updateValueFromDataVariable = options.updateValueFromDataVariable;
this.dynamicVariable = options.dataVariable;
this.updateValueFromDynamicVariable = options.updateValueFromDataVariable;

this.listenToDataVariable();
this.listenToDynamicVariable();
}

private onChange = () => {
const value = this.dataVariable.getDataValue();
this.updateValueFromDataVariable(value);
const value = this.dynamicVariable.getDataValue();
this.updateValueFromDynamicVariable(value);
};

listenToDataVariable() {
const { em, dataVariable, model } = this;
const { path } = dataVariable.attributes;
const normPath = stringToPath(path || '').join('.');
const [ds, dr] = this.em.DataSources.fromPath(path);

listenToDynamicVariable() {
const { em, dynamicVariable, model } = this;
this.removeListeners();

const type = dynamicVariable.get('type');
let dataListeners: DataVariableListener[] = [];
switch (type) {
case DataVariableType:
dataListeners = this.listenToDataVariable(dynamicVariable, em);
break;
}
dataListeners.forEach((ls) => model.listenTo(ls.obj, ls.event, this.onChange));

this.dataListeners = dataListeners;
}

private listenToDataVariable(dataVariable: DataVariable | ComponentDataVariable, em: EditorModel) {
const dataListeners: DataVariableListener[] = [];
const { path } = dataVariable.attributes;
const normPath = stringToPath(path || '').join('.');
const [ds, dr] = this.em.DataSources.fromPath(path);
ds && dataListeners.push({ obj: ds.records, event: 'add remove reset' });
dr && dataListeners.push({ obj: dr, event: 'change' });
dataListeners.push(
Expand All @@ -51,9 +63,7 @@ export default class DataVariableListenerManager {
{ obj: em, event: `${DataSourcesEvents.path}:${normPath}` },
);

dataListeners.forEach((ls) => model.listenTo(ls.obj, ls.event, this.onChange));

this.dataListeners = dataListeners;
return dataListeners;
}

private removeListeners() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ComponentView from '../../dom_components/view/ComponentView';
import ComponentDataVariable from '../model/ComponentDataVariable';
import DataVariableListenerManager from '../model/DataVariableListenerManager';
import DynamicVariableListenerManager from '../model/DataVariableListenerManager';

export default class ComponentDataVariableView extends ComponentView<ComponentDataVariable> {
dataVariableListener?: DataVariableListenerManager;
dynamicVariableListener?: DynamicVariableListenerManager;

initialize(opt = {}) {
super.initialize(opt);
this.dataVariableListener = new DataVariableListenerManager({
this.dynamicVariableListener = new DynamicVariableListenerManager({
model: this,
em: this.em!,
dataVariable: this.model,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/dom_components/model/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,8 +927,8 @@ export default class Component extends StyleableModel<ComponentProperties> {
if (name && value) attrs[name] = value;
}

if (trait.dataVariable) {
traitDataVariableAttr[name] = trait.dataVariable;
if (trait.dynamicVariable) {
traitDataVariableAttr[name] = trait.dynamicVariable;
}
});
traits.length && this.set('attributes', attrs);
Expand Down
24 changes: 16 additions & 8 deletions packages/core/src/domain_abstract/model/StyleableModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { shallowDiff } from '../../utils/mixins';
import EditorModel from '../../editor/model/Editor';
import StyleDataVariable from '../../data_sources/model/StyleDataVariable';
import { DataVariableType } from '../../data_sources/model/DataVariable';
import DataVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import CssRuleView from '../../css_composer/view/CssRuleView';
import ComponentView from '../../dom_components/view/ComponentView';
import Frame from '../../canvas/model/Frame';
Expand Down Expand Up @@ -39,7 +39,7 @@ export const getLastStyleValue = (value: string | string[]) => {

export default class StyleableModel<T extends ObjectHash = any> extends Model<T> {
em?: EditorModel;
dataVariableListeners: Record<string, DataVariableListenerManager> = {};
dynamicVariableListeners: Record<string, DynamicVariableListenerManager> = {};
views: StyleableView[] = [];

constructor(attributes: T, options: { em?: EditorModel } = {}) {
Expand Down Expand Up @@ -114,9 +114,17 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>

const styleValue = newStyle[key];
if (typeof styleValue === 'object' && styleValue.type === DataVariableType) {
const styleDataVariable = new StyleDataVariable(styleValue, { em: this.em });
newStyle[key] = styleDataVariable;
this.manageDataVariableListener(styleDataVariable, key);
const dynamicType = styleValue.type;
let styleDynamicVariable;
switch (dynamicType) {
case DataVariableType:
styleDynamicVariable = new StyleDataVariable(styleValue, { em: this.em });
break;
default:
throw new Error(`Invalid data variable type. Expected '${DataVariableType}', but found '${dynamicType}'.`);
}
artf marked this conversation as resolved.
Show resolved Hide resolved
newStyle[key] = styleDynamicVariable;
this.manageDataVariableListener(styleDynamicVariable, key);
}
});

Expand Down Expand Up @@ -146,10 +154,10 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
* Manage DataVariableListenerManager for a style property
*/
manageDataVariableListener(dataVar: StyleDataVariable, styleProp: string) {
if (this.dataVariableListeners[styleProp]) {
this.dataVariableListeners[styleProp].listenToDataVariable();
if (this.dynamicVariableListeners[styleProp]) {
this.dynamicVariableListeners[styleProp].listenToDynamicVariable();
} else {
this.dataVariableListeners[styleProp] = new DataVariableListenerManager({
this.dynamicVariableListeners[styleProp] = new DynamicVariableListenerManager({
model: this,
em: this.em!,
dataVariable: dataVar,
Expand Down
33 changes: 17 additions & 16 deletions packages/core/src/trait_manager/model/Trait.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import { isDef } from '../../utils/mixins';
import TraitsEvents, { TraitGetValueOptions, TraitOption, TraitProperties, TraitSetValueOptions } from '../types';
import TraitView from '../view/TraitView';
import Traits from './Traits';
import { DataVariableListener } from '../../data_sources/types';
import TraitDataVariable from '../../data_sources/model/TraitDataVariable';
import { DataVariableType } from '../../data_sources/model/DataVariable';
import DataVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';

/**
* @property {String} id Trait id, eg. `my-trait-id`.
Expand All @@ -30,9 +29,8 @@ export default class Trait extends Model<TraitProperties> {
em: EditorModel;
view?: TraitView;
el?: HTMLElement;
dataListeners: DataVariableListener[] = [];
dataVariable?: TraitDataVariable;
dataVariableListener?: DataVariableListenerManager;
dynamicVariable?: TraitDataVariable;
dynamicVariableListener?: DynamicVariableListenerManager;

defaults() {
return {
Expand All @@ -59,19 +57,22 @@ export default class Trait extends Model<TraitProperties> {
}
this.em = em;

if (
this.attributes.value &&
typeof this.attributes.value === 'object' &&
this.attributes.value.type === DataVariableType
) {
this.dataVariable = new TraitDataVariable(this.attributes.value, { em: this.em, trait: this });
if (this.attributes.value && typeof this.attributes.value === 'object') {
const dataType = this.attributes.value.type;
switch (dataType) {
case DataVariableType:
this.dynamicVariable = new TraitDataVariable(this.attributes.value, { em: this.em, trait: this });
break;
default:
throw new Error(`Invalid data variable type. Expected '${DataVariableType}', but found '${dataType}'.`);
}

const dv = this.dataVariable.getDataValue();
const dv = this.dynamicVariable.getDataValue();
this.set({ value: dv });
this.dataVariableListener = new DataVariableListenerManager({
this.dynamicVariableListener = new DynamicVariableListenerManager({
model: this,
em: this.em,
dataVariable: this.dataVariable,
dataVariable: this.dynamicVariable,
updateValueFromDataVariable: this.updateValueFromDataVariable.bind(this),
});
}
Expand Down Expand Up @@ -159,8 +160,8 @@ export default class Trait extends Model<TraitProperties> {
* @returns {any}
*/
getValue(opts?: TraitGetValueOptions) {
if (this.dataVariable) {
const dValue = this.dataVariable.getDataValue();
if (this.dynamicVariable) {
const dValue = this.dynamicVariable.getDataValue();

return dValue;
}
Expand Down