Browse Source

init: add traits

ci/dependabot
danstarns 2 years ago
parent
commit
21930e8c4c
  1. 57
      src/trait_manager/model/Trait.ts
  2. 51
      src/trait_manager/model/TraitDataVariable.ts
  3. 49
      test/specs/data_sources/index.ts

57
src/trait_manager/model/Trait.ts

@ -1,12 +1,14 @@
import { isString, isUndefined } from 'underscore'; import { isString, isUndefined, keys } from 'underscore';
import Category from '../../abstract/ModuleCategory'; import Category from '../../abstract/ModuleCategory';
import { LocaleOptions, Model, SetOptions } from '../../common'; import { LocaleOptions, Model, SetOptions } from '../../common';
import Component from '../../dom_components/model/Component'; import Component from '../../dom_components/model/Component';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import { isDef } from '../../utils/mixins'; 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';
/** /**
* @property {String} id Trait id, eg. `my-trait-id`. * @property {String} id Trait id, eg. `my-trait-id`.
@ -26,6 +28,8 @@ export default class Trait extends Model<TraitProperties> {
em: EditorModel; em: EditorModel;
view?: TraitView; view?: TraitView;
el?: HTMLElement; el?: HTMLElement;
dataListeners: DataVariableListener[] = [];
dataVariable?: TraitDataVariable;
defaults() { defaults() {
return { return {
@ -51,6 +55,18 @@ export default class Trait extends Model<TraitProperties> {
this.setTarget(target); this.setTarget(target);
} }
this.em = em; this.em = em;
if (
this.attributes.value &&
typeof this.attributes.value === 'object' &&
this.attributes.value.type === 'data-variable'
) {
this.dataVariable = new TraitDataVariable(this.attributes.value, { em: this.em, trait: this });
const dv = this.dataVariable.getDataValue();
this.set({ value: dv });
this.listenToDataVariable(this.dataVariable);
}
} }
get parent() { get parent() {
@ -85,6 +101,32 @@ export default class Trait extends Model<TraitProperties> {
} }
} }
listenToDataVariable(dataVar: TraitDataVariable) {
const { em } = this;
const { path } = dataVar.attributes;
const normPath = stringToPath(path || '').join('.');
const dataListeners: DataVariableListener[] = [];
const prevListeners = this.dataListeners || [];
prevListeners.forEach(ls => this.stopListening(ls.obj, ls.event, this.updateValueFromDataVariable));
dataListeners.push({ obj: dataVar, event: 'change:value' });
dataListeners.push({ obj: em, event: `${DataSourcesEvents.path}:${normPath}` });
dataListeners.forEach(ls =>
this.listenTo(ls.obj, ls.event, () => {
const dr = dataVar.getDataValue();
this.updateValueFromDataVariable(dr);
})
);
this.dataListeners = dataListeners;
}
updateValueFromDataVariable(value: string) {
this.setTargetValue(value);
this.trigger('change:value');
}
/** /**
* Get the trait id. * Get the trait id.
* @returns {String} * @returns {String}
@ -130,6 +172,12 @@ export default class Trait extends Model<TraitProperties> {
* @returns {any} * @returns {any}
*/ */
getValue(opts?: TraitGetValueOptions) { getValue(opts?: TraitGetValueOptions) {
if (this.dataVariable) {
const dValue = this.dataVariable.getDataValue();
return dValue;
}
return this.getTargetValue(opts); return this.getTargetValue(opts);
} }
@ -146,6 +194,11 @@ 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') {
// value = new TraitDataVariable(value, { em: this.em, trait: this }).initialize();
// this.listenToDataVariable(value);
// }
if (setValue) { if (setValue) {
setValue({ setValue({
value, value,

51
src/trait_manager/model/TraitDataVariable.ts

@ -0,0 +1,51 @@
import { Model } from '../../common';
import EditorModel from '../../editor/model/Editor';
import { stringToPath } from '../../utils/mixins';
import Trait from './Trait';
export default class TraitDataVariable extends Model {
em?: EditorModel;
trait?: Trait;
defaults() {
return {
type: 'data-variable',
value: '',
path: '',
};
}
initialize(attrs: any, options: any) {
super.initialize(attrs, options);
this.em = options.em;
this.trait = options.trait;
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);
}
}
getDataValue() {
const { path } = this.attributes;
const [dsId, drId, key] = stringToPath(path);
const ds = this?.em?.DataSources.get(dsId);
const dr = ds && ds.getRecord(drId);
const dv = dr?.get(key);
return dv;
}
onDataSourceChange() {
const dv = this.getDataValue();
this?.trait?.setTargetValue(dv);
}
}

49
test/specs/data_sources/index.ts

@ -298,6 +298,55 @@ describe('DataSourceManager', () => {
}); });
}); });
describe('Traits', () => {
let fixtures: HTMLElement;
let cmpRoot: ComponentWrapper;
beforeEach(() => {
document.body.innerHTML = '<div id="fixtures"></div>';
const { Pages, Components } = em;
Pages.onLoad();
cmpRoot = Components.getWrapper()!;
const View = Components.getType('wrapper')!.view;
const wrapperEl = new View({
model: cmpRoot,
config: { ...cmpRoot.config, em },
});
wrapperEl.render();
fixtures = document.body.querySelector('#fixtures')!;
fixtures.appendChild(wrapperEl.el);
});
test('component initializes with data-variable trait input', () => {
const inputDataSource: DataSourceProps = {
id: 'test-input',
records: [{ id: 'id1', value: 'test-value' }],
};
dsm.add(inputDataSource);
const cmp = cmpRoot.append({
tagName: 'input',
traits: [
'name',
'type',
{
type: 'text',
label: 'Value',
name: 'value',
value: {
type: 'data-variable',
value: 'default',
path: 'test-input.id1.value',
},
},
],
})[0];
const input = cmp.getEl();
expect(input?.getAttribute('value')).toBe('test-value');
});
});
test('add DataSource with records', () => { test('add DataSource with records', () => {
const eventAdd = jest.fn(); const eventAdd = jest.fn();
em.on(dsm.events.add, eventAdd); em.on(dsm.events.add, eventAdd);

Loading…
Cancel
Save