Browse Source

refactor: use base data var class and move code into data_sources dire

ci/dependabot
danstarns 2 years ago
parent
commit
ecf07e076f
  1. 10
      src/data_sources/model/ComponentDataVariable.ts
  2. 24
      src/data_sources/model/DataVariable.ts
  3. 39
      src/data_sources/model/StyleDataVariable.ts
  4. 18
      src/data_sources/model/TraitDataVariable.ts
  5. 6
      src/data_sources/view/ComponentDataVariableView.ts
  6. 7
      src/dom_components/index.ts
  7. 3
      src/dom_components/model/types.ts
  8. 15
      src/domain_abstract/model/StyleableModel.ts
  9. 7
      src/style_manager/model/PropertyComposite.ts
  10. 13
      src/trait_manager/model/Trait.ts
  11. 23
      test/specs/data_sources/index.ts

10
src/dom_components/model/ComponentDataVariable.ts → src/data_sources/model/ComponentDataVariable.ts

@ -1,15 +1,15 @@
import Component from '../../dom_components/model/Component';
import { ToHTMLOptions } from '../../dom_components/model/types';
import { stringToPath, toLowerCase } from '../../utils/mixins'; import { stringToPath, toLowerCase } from '../../utils/mixins';
import Component from './Component'; import { DataVariableType } from './DataVariable';
import { ToHTMLOptions } from './types';
export const type = 'data-variable';
export default class ComponentDataVariable extends Component { export default class ComponentDataVariable extends Component {
get defaults() { get defaults() {
return { return {
// @ts-ignore // @ts-ignore
...super.defaults, ...super.defaults,
type, type: DataVariableType,
path: '', path: '',
value: '', value: '',
}; };
@ -25,6 +25,6 @@ export default class ComponentDataVariable extends Component {
} }
static isComponent(el: HTMLElement) { static isComponent(el: HTMLElement) {
return toLowerCase(el.tagName) === type; return toLowerCase(el.tagName) === DataVariableType;
} }
} }

24
src/trait_manager/model/TraitDataVariable.ts → src/data_sources/model/DataVariable.ts

@ -1,15 +1,15 @@
import { Model } from '../../common'; import { Model } from '../../common';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import { stringToPath } from '../../utils/mixins'; import { stringToPath } from '../../utils/mixins';
import Trait from './Trait';
export default class TraitDataVariable extends Model { export const DataVariableType = 'data-variable';
export default class DataVariable extends Model {
em?: EditorModel; em?: EditorModel;
trait?: Trait;
defaults() { defaults() {
return { return {
type: 'data-variable', type: DataVariableType,
value: '', value: '',
path: '', path: '',
}; };
@ -18,8 +18,6 @@ export default class TraitDataVariable extends Model {
initialize(attrs: any, options: any) { initialize(attrs: any, options: any) {
super.initialize(attrs, options); super.initialize(attrs, options);
this.em = options.em; this.em = options.em;
this.trait = options.trait;
this.listenToDataSource(); this.listenToDataSource();
return this; return this;
@ -34,18 +32,16 @@ export default class TraitDataVariable extends Model {
} }
} }
onDataSourceChange() {
const newValue = this.getDataValue();
this.set({ value: newValue });
}
getDataValue() { getDataValue() {
const { path } = this.attributes; const { path } = this.attributes;
const [dsId, drId, key] = stringToPath(path); const [dsId, drId, key] = stringToPath(path);
const ds = this?.em?.DataSources.get(dsId); const ds = this?.em?.DataSources.get(dsId);
const dr = ds && ds.getRecord(drId); const dr = ds && ds.getRecord(drId);
const dv = dr?.get(key); return dr?.get(key);
return dv;
}
onDataSourceChange() {
const dv = this.getDataValue();
this?.trait?.setTargetValue(dv);
} }
} }

39
src/data_sources/model/StyleDataVariable.ts

@ -1,42 +1,9 @@
import { Model } from '../../common'; import DataVariable from './DataVariable';
import EditorModel from '../../editor/model/Editor';
import { get, stringToPath } from '../../utils/mixins';
export default class StyleDataVariable extends Model {
em?: EditorModel;
export default class StyleDataVariable extends DataVariable {
defaults() { defaults() {
return { return {
type: 'data-variable-css', ...super.defaults(),
value: '',
path: '',
}; };
} }
initialize(attrs: any, options: any) {
super.initialize(attrs, options);
this.em = options.em;
this.listenToDataSource();
return this;
}
listenToDataSource() {
const { path } = this.attributes;
const resolvedPath = stringToPath(path).join('.');
if (this.em) {
this.listenTo(this.em.DataSources, `change:${resolvedPath}`, this.onDataSourceChange);
}
}
onDataSourceChange() {
const { path } = this.attributes;
const [dsId, drId, key] = stringToPath(path);
const ds = this?.em?.DataSources.get(dsId);
const dr = ds && ds.getRecord(drId);
const newValue = dr?.get(key);
this.set({ value: newValue });
}
} }

18
src/data_sources/model/TraitDataVariable.ts

@ -0,0 +1,18 @@
import DataVariable from './DataVariable';
import Trait from '../../trait_manager/model/Trait';
export default class TraitDataVariable extends DataVariable {
trait?: Trait;
initialize(attrs: any, options: any) {
super.initialize(attrs, options);
this.trait = options.trait;
return this;
}
onDataSourceChange() {
const newValue = this.getDataValue();
this.trait?.setTargetValue(newValue);
}
}

6
src/dom_components/view/ComponentDataVariableView.ts → src/data_sources/view/ComponentDataVariableView.ts

@ -1,7 +1,7 @@
import { DataSourcesEvents, DataVariableListener } from '../../data_sources/types'; import { DataSourcesEvents, DataVariableListener } from '../../data_sources/types';
import ComponentView from '../../dom_components/view/ComponentView';
import { stringToPath } from '../../utils/mixins'; import { stringToPath } from '../../utils/mixins';
import ComponentDataVariable from '../model/ComponentDataVariable'; import ComponentDataVariable from '../model/ComponentDataVariable';
import ComponentView from './ComponentView';
export default class ComponentDataVariableView extends ComponentView<ComponentDataVariable> { export default class ComponentDataVariableView extends ComponentView<ComponentDataVariable> {
dataListeners: DataVariableListener[] = []; dataListeners: DataVariableListener[] = [];
@ -24,7 +24,7 @@ export default class ComponentDataVariableView extends ComponentView<ComponentDa
const dataListeners: DataVariableListener[] = []; const dataListeners: DataVariableListener[] = [];
const prevListeners = this.dataListeners || []; const prevListeners = this.dataListeners || [];
prevListeners.forEach(ls => this.stopListening(ls.obj, ls.event, this.postRender)); prevListeners.forEach((ls) => this.stopListening(ls.obj, ls.event, this.postRender));
ds && dataListeners.push({ obj: ds.records, event: 'add remove reset' }); ds && dataListeners.push({ obj: ds.records, event: 'add remove reset' });
dr && dataListeners.push({ obj: dr, event: 'change' }); dr && dataListeners.push({ obj: dr, event: 'change' });
@ -34,7 +34,7 @@ export default class ComponentDataVariableView extends ComponentView<ComponentDa
{ obj: em, event: `${DataSourcesEvents.path}:${normPath}` } { obj: em, event: `${DataSourcesEvents.path}:${normPath}` }
); );
dataListeners.forEach(ls => this.listenTo(ls.obj, ls.event, this.postRender)); dataListeners.forEach((ls) => this.listenTo(ls.obj, ls.event, this.postRender));
this.dataListeners = dataListeners; this.dataListeners = dataListeners;
} }

7
src/dom_components/index.ts

@ -101,8 +101,6 @@ import ComponentVideoView from './view/ComponentVideoView';
import ComponentView, { IComponentView } from './view/ComponentView'; import ComponentView, { IComponentView } from './view/ComponentView';
import ComponentWrapperView from './view/ComponentWrapperView'; import ComponentWrapperView from './view/ComponentWrapperView';
import ComponentsView from './view/ComponentsView'; import ComponentsView from './view/ComponentsView';
import ComponentDataVariable, { type as typeVariable } from './model/ComponentDataVariable';
import ComponentDataVariableView from './view/ComponentDataVariableView';
import ComponentHead, { type as typeHead } from './model/ComponentHead'; import ComponentHead, { type as typeHead } from './model/ComponentHead';
import { import {
getSymbolMain, getSymbolMain,
@ -116,6 +114,9 @@ import {
import { ComponentsEvents, SymbolInfo } from './types'; import { ComponentsEvents, SymbolInfo } from './types';
import Symbols from './model/Symbols'; import Symbols from './model/Symbols';
import { BlockProperties } from '../block_manager/model/Block'; import { BlockProperties } from '../block_manager/model/Block';
import ComponentDataVariable from '../data_sources/model/ComponentDataVariable';
import ComponentDataVariableView from '../data_sources/view/ComponentDataVariableView';
import { DataVariableType } from '../data_sources/model/DataVariable';
export type ComponentEvent = export type ComponentEvent =
| 'component:create' | 'component:create'
@ -182,7 +183,7 @@ export interface CanMoveResult {
export default class ComponentManager extends ItemManagerModule<DomComponentsConfig, any> { export default class ComponentManager extends ItemManagerModule<DomComponentsConfig, any> {
componentTypes: ComponentStackItem[] = [ componentTypes: ComponentStackItem[] = [
{ {
id: typeVariable, id: DataVariableType,
model: ComponentDataVariable, model: ComponentDataVariable,
view: ComponentDataVariableView, view: ComponentDataVariableView,
}, },

3
src/dom_components/model/types.ts

@ -11,6 +11,7 @@ import Component from './Component';
import Components from './Components'; import Components from './Components';
import { ToolbarButtonProps } from './ToolbarButton'; import { ToolbarButtonProps } from './ToolbarButton';
import { ParseNodeOptions } from '../../parser/config/config'; import { ParseNodeOptions } from '../../parser/config/config';
import { DataVariableType } from '../../data_sources/model/DataVariable';
export type DragMode = 'translate' | 'absolute' | ''; export type DragMode = 'translate' | 'absolute' | '';
@ -175,7 +176,7 @@ export interface ComponentProperties {
* Component default style, eg. `{ width: '100px', height: '100px', 'background-color': 'red' }` * Component default style, eg. `{ width: '100px', height: '100px', 'background-color': 'red' }`
* @default {} * @default {}
*/ */
style?: string | Record<string, any | { type: 'data-variable'; path: string; value: string }>; style?: string | Record<string, any | { type: typeof DataVariableType; path: string; value: string }>;
/** /**
* Component related styles, eg. `.my-component-class { color: red }` * Component related styles, eg. `.my-component-class { color: red }`
* @default '' * @default ''

15
src/domain_abstract/model/StyleableModel.ts

@ -6,13 +6,14 @@ import { shallowDiff, stringToPath } 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 { DataSourcesEvents, DataVariableListener } from '../../data_sources/types'; import { DataSourcesEvents, DataVariableListener } from '../../data_sources/types';
import { DataVariableType } from '../../data_sources/model/DataVariable';
export type StyleProps = Record< export type StyleProps = Record<
string, string,
| string | string
| string[] | string[]
| { | {
type: 'data-variable-css'; type: typeof DataVariableType;
value: string; value: string;
path: string; path: string;
} }
@ -92,7 +93,7 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
const propNew = { ...prop }; const propNew = { ...prop };
const newStyle = { ...propNew }; const newStyle = { ...propNew };
keys(newStyle).forEach(key => { keys(newStyle).forEach((key) => {
// Remove empty style properties // Remove empty style properties
if (newStyle[key] === '') { if (newStyle[key] === '') {
delete newStyle[key]; delete newStyle[key];
@ -101,7 +102,7 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
} }
const styleValue = newStyle[key]; const styleValue = newStyle[key];
if (typeof styleValue === 'object' && styleValue.type === 'data-variable-css') { if (typeof styleValue === 'object' && styleValue.type === DataVariableType) {
newStyle[key] = new StyleDataVariable(styleValue, { em: this.em }); newStyle[key] = new StyleDataVariable(styleValue, { em: this.em });
} }
}); });
@ -112,7 +113,7 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
// Delete the property used for partial updates // Delete the property used for partial updates
delete diff.__p; delete diff.__p;
keys(diff).forEach(pr => { keys(diff).forEach((pr) => {
const { em } = this; const { em } = this;
if (opts.noEvent) { if (opts.noEvent) {
return; return;
@ -140,12 +141,12 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
const dataListeners: DataVariableListener[] = []; const dataListeners: DataVariableListener[] = [];
const prevListeners = this.dataListeners || []; const prevListeners = this.dataListeners || [];
prevListeners.forEach(ls => this.stopListening(ls.obj, ls.event, this.updateStyleProp)); prevListeners.forEach((ls) => this.stopListening(ls.obj, ls.event, this.updateStyleProp));
dataListeners.push({ obj: dataVar, event: 'change:value' }); dataListeners.push({ obj: dataVar, event: 'change:value' });
dataListeners.push({ obj: em, event: `${DataSourcesEvents.path}:${normPath}` }); dataListeners.push({ obj: em, event: `${DataSourcesEvents.path}:${normPath}` });
dataListeners.forEach(ls => dataListeners.forEach((ls) =>
this.listenTo(ls.obj, ls.event, () => { this.listenTo(ls.obj, ls.event, () => {
const [dsId, drId, keyPath] = stringToPath(path); const [dsId, drId, keyPath] = stringToPath(path);
const ds = em?.DataSources.get(dsId); const ds = em?.DataSources.get(dsId);
@ -167,7 +168,7 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
resolveDataVariables(style: StyleProps): StyleProps { resolveDataVariables(style: StyleProps): StyleProps {
const resolvedStyle = { ...style }; const resolvedStyle = { ...style };
keys(resolvedStyle).forEach(key => { keys(resolvedStyle).forEach((key) => {
const styleValue = resolvedStyle[key]; const styleValue = resolvedStyle[key];
if (styleValue instanceof StyleDataVariable) { if (styleValue instanceof StyleDataVariable) {

7
src/style_manager/model/PropertyComposite.ts

@ -5,6 +5,7 @@ import Properties from './Properties';
import Property, { OptionsStyle, OptionsUpdate, PropertyProps } from './Property'; import Property, { OptionsStyle, OptionsUpdate, PropertyProps } from './Property';
import { PropertyNumberProps } from './PropertyNumber'; import { PropertyNumberProps } from './PropertyNumber';
import { PropertySelectProps } from './PropertySelect'; import { PropertySelectProps } from './PropertySelect';
import { DataVariableType } from '../../data_sources/model/DataVariable';
export const isNumberType = (type: string) => type === 'integer' || type === 'number'; export const isNumberType = (type: string) => type === 'integer' || type === 'number';
@ -277,7 +278,7 @@ export default class PropertyComposite<T extends Record<string, any> = PropertyC
const result = this.getStyleFromProps()[this.getName()] || ''; const result = this.getStyleFromProps()[this.getName()] || '';
if (result && typeof result !== 'string' && 'type' in result) { if (result && typeof result !== 'string' && 'type' in result) {
if (result.type === 'data-variable-css') { if (result.type === DataVariableType) {
console.log('Datasources __getFullValue'); console.log('Datasources __getFullValue');
} }
} }
@ -309,7 +310,7 @@ export default class PropertyComposite<T extends Record<string, any> = PropertyC
const value = style[name]; const value = style[name];
if (value && typeof value !== 'string' && 'type' in value) { if (value && typeof value !== 'string' && 'type' in value) {
if (value.type === 'data-variable-css') { if (value.type === DataVariableType) {
console.log('Datasources __splitStyleName'); console.log('Datasources __splitStyleName');
} }
} }
@ -357,7 +358,7 @@ export default class PropertyComposite<T extends Record<string, any> = PropertyC
const value = style[name]; const value = style[name];
if (value && typeof value !== 'string' && 'type' in value) { if (value && typeof value !== 'string' && 'type' in value) {
if (value.type === 'data-variable-css') { if (value.type === DataVariableType) {
console.log('Datasources __getPropsFromStyle'); console.log('Datasources __getPropsFromStyle');
} }
} }

13
src/trait_manager/model/Trait.ts

@ -7,8 +7,9 @@ import { isDef, stringToPath } from '../../utils/mixins';
import TraitsEvents, { TraitGetValueOptions, TraitOption, TraitProperties, TraitSetValueOptions } from '../types'; import TraitsEvents, { TraitGetValueOptions, TraitOption, TraitProperties, TraitSetValueOptions } from '../types';
import TraitView from '../view/TraitView'; import TraitView from '../view/TraitView';
import Traits from './Traits'; import Traits from './Traits';
import TraitDataVariable from './TraitDataVariable';
import { DataSourcesEvents, DataVariableListener } from '../../data_sources/types'; import { DataSourcesEvents, DataVariableListener } from '../../data_sources/types';
import TraitDataVariable from '../../data_sources/model/TraitDataVariable';
import { DataVariableType } from '../../data_sources/model/DataVariable';
/** /**
* @property {String} id Trait id, eg. `my-trait-id`. * @property {String} id Trait id, eg. `my-trait-id`.
@ -59,7 +60,7 @@ export default class Trait extends Model<TraitProperties> {
if ( if (
this.attributes.value && this.attributes.value &&
typeof this.attributes.value === 'object' && typeof this.attributes.value === 'object' &&
this.attributes.value.type === 'data-variable' this.attributes.value.type === DataVariableType
) { ) {
this.dataVariable = new TraitDataVariable(this.attributes.value, { em: this.em, trait: this }); this.dataVariable = new TraitDataVariable(this.attributes.value, { em: this.em, trait: this });
@ -108,12 +109,12 @@ export default class Trait extends Model<TraitProperties> {
const dataListeners: DataVariableListener[] = []; const dataListeners: DataVariableListener[] = [];
const prevListeners = this.dataListeners || []; const prevListeners = this.dataListeners || [];
prevListeners.forEach(ls => this.stopListening(ls.obj, ls.event, this.updateValueFromDataVariable)); prevListeners.forEach((ls) => this.stopListening(ls.obj, ls.event, this.updateValueFromDataVariable));
dataListeners.push({ obj: dataVar, event: 'change:value' }); dataListeners.push({ obj: dataVar, event: 'change:value' });
dataListeners.push({ obj: em, event: `${DataSourcesEvents.path}:${normPath}` }); dataListeners.push({ obj: em, event: `${DataSourcesEvents.path}:${normPath}` });
dataListeners.forEach(ls => dataListeners.forEach((ls) =>
this.listenTo(ls.obj, ls.event, () => { this.listenTo(ls.obj, ls.event, () => {
const dr = dataVar.getDataValue(); const dr = dataVar.getDataValue();
this.updateValueFromDataVariable(dr); this.updateValueFromDataVariable(dr);
@ -194,7 +195,7 @@ export default class Trait extends Model<TraitProperties> {
const valueOpts: { avoidStore?: boolean } = {}; const valueOpts: { avoidStore?: boolean } = {};
const { setValue } = this.attributes; const { setValue } = this.attributes;
// if (value && typeof value === 'object' && value.type === 'data-variable') { // if (value && typeof value === 'object' && value.type === DataVariableType) {
// value = new TraitDataVariable(value, { em: this.em, trait: this }).initialize(); // value = new TraitDataVariable(value, { em: this.em, trait: this }).initialize();
// this.listenToDataVariable(value); // this.listenToDataVariable(value);
// } // }
@ -240,7 +241,7 @@ export default class Trait extends Model<TraitProperties> {
*/ */
getOption(id?: string): TraitOption | undefined { getOption(id?: string): TraitOption | undefined {
const idSel = isDef(id) ? id : this.getValue(); const idSel = isDef(id) ? id : this.getValue();
return this.getOptions().filter(o => this.getOptionId(o) === idSel)[0]; return this.getOptions().filter((o) => this.getOptionId(o) === idSel)[0];
} }
/** /**

23
test/specs/data_sources/index.ts

@ -2,7 +2,8 @@ import Editor from '../../../src/editor/model/Editor';
import DataSourceManager from '../../../src/data_sources'; import DataSourceManager from '../../../src/data_sources';
import { DataSourceProps, DataSourcesEvents } from '../../../src/data_sources/types'; import { DataSourceProps, DataSourcesEvents } from '../../../src/data_sources/types';
import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper'; import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper';
import ComponentDataVariable from '../../../src/dom_components/model/ComponentDataVariable'; import ComponentDataVariable from '../../../src/data_sources/model/ComponentDataVariable';
import { DataVariableType } from '../../../src/data_sources/model/DataVariable';
describe('DataSourceManager', () => { describe('DataSourceManager', () => {
let em: Editor; let em: Editor;
@ -66,7 +67,7 @@ describe('DataSourceManager', () => {
content: 'Hello World', content: 'Hello World',
style: { style: {
color: { color: {
type: 'data-variable-css', type: DataVariableType,
value: 'black', value: 'black',
path: 'colors-data.id1.color', path: 'colors-data.id1.color',
}, },
@ -90,7 +91,7 @@ describe('DataSourceManager', () => {
content: 'Hello World', content: 'Hello World',
style: { style: {
color: { color: {
type: 'data-variable-css', type: DataVariableType,
value: 'black', value: 'black',
path: 'colors-data.id1.color', path: 'colors-data.id1.color',
}, },
@ -114,7 +115,7 @@ describe('DataSourceManager', () => {
content: 'Hello World', content: 'Hello World',
style: { style: {
color: { color: {
type: 'data-variable-css', type: DataVariableType,
value: 'black', value: 'black',
path: 'unknown.id1.color', path: 'unknown.id1.color',
}, },
@ -163,7 +164,7 @@ describe('DataSourceManager', () => {
type: 'text', type: 'text',
components: [ components: [
{ {
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path: 'test-data-source.id1.content', path: 'test-data-source.id1.content',
}, },
@ -205,7 +206,7 @@ describe('DataSourceManager', () => {
type: 'text', type: 'text',
components: [ components: [
{ {
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path: 'test-data-source.id1.content', path: 'test-data-source.id1.content',
}, },
@ -245,7 +246,7 @@ describe('DataSourceManager', () => {
type: 'text', type: 'text',
components: [ components: [
{ {
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path: 'test-data-source.id1.content', path: 'test-data-source.id1.content',
}, },
@ -281,7 +282,7 @@ describe('DataSourceManager', () => {
type: 'text', type: 'text',
components: [ components: [
{ {
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path: 'test-data-source.id1.content', path: 'test-data-source.id1.content',
}, },
@ -335,7 +336,7 @@ describe('DataSourceManager', () => {
label: 'Value', label: 'Value',
name: 'value', name: 'value',
value: { value: {
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path: 'test-input.id1.value', path: 'test-input.id1.value',
}, },
@ -364,7 +365,7 @@ describe('DataSourceManager', () => {
label: 'Value', label: 'Value',
name: 'value', name: 'value',
value: { value: {
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path: 'test-input.id1.value', path: 'test-input.id1.value',
}, },
@ -413,7 +414,7 @@ describe('DataSourceManager', () => {
const addDataVariable = (path = 'ds1.id1.name') => const addDataVariable = (path = 'ds1.id1.name') =>
cmpRoot.append<ComponentDataVariable>({ cmpRoot.append<ComponentDataVariable>({
type: 'data-variable', type: DataVariableType,
value: 'default', value: 'default',
path, path,
})[0]; })[0];

Loading…
Cancel
Save