Browse Source

feat: make DataSources work with .loadProjectData

feature/data-sources
danstarns 2 years ago
parent
commit
3be94a9994
  1. 10
      src/dom_components/model/Component.ts
  2. 13
      src/domain_abstract/model/StyleableModel.ts
  3. 232
      test/specs/data_sources/serialization.ts

10
src/dom_components/model/Component.ts

@ -51,6 +51,7 @@ import {
updateSymbolComps, updateSymbolComps,
updateSymbolProps, updateSymbolProps,
} from './SymbolUtils'; } from './SymbolUtils';
import TraitDataVariable from '../../data_sources/model/TraitDataVariable';
export interface IComponent extends ExtractMethods<Component> {} export interface IComponent extends ExtractMethods<Component> {}
@ -744,6 +745,14 @@ export default class Component extends StyleableModel<ComponentProperties> {
} }
} }
const attrDataVariable = this.get('attributes-data-variable');
if (attrDataVariable) {
Object.entries(attrDataVariable).forEach(([key, value]) => {
const dataVariable = value instanceof TraitDataVariable ? value : new TraitDataVariable(value, { em });
attributes[key] = dataVariable.getDataValue();
});
}
// Check if we need an ID on the component // Check if we need an ID on the component
if (!has(attributes, 'id')) { if (!has(attributes, 'id')) {
let addId = false; let addId = false;
@ -895,7 +904,6 @@ export default class Component extends StyleableModel<ComponentProperties> {
} }
}); });
traits.length && this.set('attributes', attrs); traits.length && this.set('attributes', attrs);
// store the trait data-variable attributes outside the attributes object so you can load a project with data-variable attributes
Object.keys(traitDataVariableAttr).length && this.set('attributes-data-variable', traitDataVariableAttr); Object.keys(traitDataVariableAttr).length && this.set('attributes-data-variable', traitDataVariableAttr);
this.on(event, this.initTraits); this.on(event, this.initTraits);
changed && em && em.trigger('component:toggled'); changed && em && em.trigger('component:toggled');

13
src/domain_abstract/model/StyleableModel.ts

@ -171,6 +171,19 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
keys(resolvedStyle).forEach((key) => { keys(resolvedStyle).forEach((key) => {
const styleValue = resolvedStyle[key]; const styleValue = resolvedStyle[key];
if (typeof styleValue === 'string' || Array.isArray(styleValue)) {
return;
}
if (
typeof styleValue === 'object' &&
styleValue.type === DataVariableType &&
!(styleValue instanceof StyleDataVariable)
) {
const dataVar = new StyleDataVariable(styleValue, { em: this.em });
resolvedStyle[key] = dataVar.getDataValue();
}
if (styleValue instanceof StyleDataVariable) { if (styleValue instanceof StyleDataVariable) {
const [dsId, drId, keyPath] = stringToPath(styleValue.get('path')); const [dsId, drId, keyPath] = stringToPath(styleValue.get('path'));
const ds = this.em?.DataSources.get(dsId); const ds = this.em?.DataSources.get(dsId);

232
test/specs/data_sources/serialization.ts

@ -4,6 +4,7 @@ import { DataSourceProps } from '../../../src/data_sources/types';
import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper'; import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper';
import { DataVariableType } from '../../../src/data_sources/model/DataVariable'; import { DataVariableType } from '../../../src/data_sources/model/DataVariable';
import EditorModel from '../../../src/editor/model/Editor'; import EditorModel from '../../../src/editor/model/Editor';
import { ProjectData } from '../../../src/storage_manager';
// Filter out the unique ids and selectors replaced with 'data-variable-id' // Filter out the unique ids and selectors replaced with 'data-variable-id'
// Makes the snapshot more stable // Makes the snapshot more stable
@ -43,13 +44,21 @@ describe('DataSource Serialization', () => {
let dsm: DataSourceManager; let dsm: DataSourceManager;
let fixtures: HTMLElement; let fixtures: HTMLElement;
let cmpRoot: ComponentWrapper; let cmpRoot: ComponentWrapper;
const datasource: DataSourceProps = { const componentDataSource: DataSourceProps = {
id: 'component-serialization', id: 'component-serialization',
records: [ records: [
{ id: 'id1', content: 'Hello World' }, { id: 'id1', content: 'Hello World' },
{ id: 'id2', color: 'red' }, { id: 'id2', color: 'red' },
], ],
}; };
const styleDataSource: DataSourceProps = {
id: 'colors-data',
records: [{ id: 'id1', color: 'red' }],
};
const traitDataSource: DataSourceProps = {
id: 'test-input',
records: [{ id: 'id1', value: 'test-value' }],
};
beforeEach(() => { beforeEach(() => {
editor = new Editor({ editor = new Editor({
@ -70,7 +79,10 @@ describe('DataSource Serialization', () => {
wrapperEl.render(); wrapperEl.render();
fixtures = document.body.querySelector('#fixtures')!; fixtures = document.body.querySelector('#fixtures')!;
fixtures.appendChild(wrapperEl.el); fixtures.appendChild(wrapperEl.el);
dsm.add(datasource);
dsm.add(componentDataSource);
dsm.add(styleDataSource);
dsm.add(traitDataSource);
}); });
afterEach(() => { afterEach(() => {
@ -85,7 +97,7 @@ describe('DataSource Serialization', () => {
{ {
type: DataVariableType, type: DataVariableType,
value: 'default', value: 'default',
path: `${datasource.id}.id1.content`, path: `${componentDataSource.id}.id1.content`,
}, },
], ],
})[0]; })[0];
@ -97,18 +109,12 @@ describe('DataSource Serialization', () => {
expect(html).toMatchInlineSnapshot('"<body><h1><div>Hello World</div></h1></body>"'); expect(html).toMatchInlineSnapshot('"<body><h1><div>Hello World</div></h1></body>"');
}); });
// DataSources TODO
test.todo('component .getCss');
// DataSources TODO
test.todo('component .getJs');
describe('.getProjectData', () => { describe('.getProjectData', () => {
test('ComponentDataVariable', () => { test('ComponentDataVariable', () => {
const dataVariable = { const dataVariable = {
type: DataVariableType, type: DataVariableType,
value: 'default', value: 'default',
path: `${datasource.id}.id1.content`, path: `${componentDataSource.id}.id1.content`,
}; };
cmpRoot.append({ cmpRoot.append({
@ -128,12 +134,6 @@ describe('DataSource Serialization', () => {
}); });
test('StyleDataVariable', () => { test('StyleDataVariable', () => {
const styleDataSource: DataSourceProps = {
id: 'colors-data',
records: [{ id: 'id1', color: 'red' }],
};
dsm.add(styleDataSource);
const dataVariable = { const dataVariable = {
type: DataVariableType, type: DataVariableType,
value: 'black', value: 'black',
@ -166,17 +166,10 @@ describe('DataSource Serialization', () => {
}); });
test('TraitDataVariable', () => { test('TraitDataVariable', () => {
const record = { id: 'id1', value: 'test-value' };
const inputDataSource: DataSourceProps = {
id: 'test-input',
records: [record],
};
dsm.add(inputDataSource);
const dataVariable = { const dataVariable = {
type: DataVariableType, type: DataVariableType,
value: 'default', value: 'default',
path: `${inputDataSource.id}.id1.value`, path: `${traitDataSource.id}.id1.value`,
}; };
cmpRoot.append({ cmpRoot.append({
@ -201,11 +194,200 @@ describe('DataSource Serialization', () => {
value: dataVariable, value: dataVariable,
}); });
expect(component.attributes).toEqual({ expect(component.attributes).toEqual({
value: record.value, value: 'test-value',
}); });
const snapshot = filterObjectForSnapshot(projectData); const snapshot = filterObjectForSnapshot(projectData);
expect(snapshot).toMatchSnapshot(``); expect(snapshot).toMatchSnapshot(``);
}); });
}); });
describe('.loadProjectData', () => {
test('ComponentDataVariable', () => {
const componentProjectData: ProjectData = {
assets: [],
pages: [
{
frames: [
{
component: {
components: [
{
components: [
{
path: 'component-serialization.id1.content',
type: 'data-variable',
value: 'default',
},
],
tagName: 'h1',
type: 'text',
},
],
docEl: {
tagName: 'html',
},
head: {
type: 'head',
},
stylable: [
'background',
'background-color',
'background-image',
'background-repeat',
'background-attachment',
'background-position',
'background-size',
],
type: 'wrapper',
},
id: 'data-variable-id',
},
],
id: 'data-variable-id',
type: 'main',
},
],
styles: [],
symbols: [],
};
editor.loadProjectData(componentProjectData);
const components = editor.getComponents();
const component = components.models[0];
const html = component.toHTML();
expect(html).toContain('Hello World');
});
test('StyleDataVariable', () => {
const componentProjectData: ProjectData = {
assets: [],
pages: [
{
frames: [
{
component: {
components: [
{
attributes: {
id: 'selectorid',
},
content: 'Hello World',
tagName: 'h1',
type: 'text',
},
],
docEl: {
tagName: 'html',
},
head: {
type: 'head',
},
stylable: [
'background',
'background-color',
'background-image',
'background-repeat',
'background-attachment',
'background-position',
'background-size',
],
type: 'wrapper',
},
id: 'componentid',
},
],
id: 'frameid',
type: 'main',
},
],
styles: [
{
selectors: ['#selectorid'],
style: {
color: {
path: 'colors-data.id1.color',
type: 'data-variable',
value: 'black',
},
},
},
],
symbols: [],
};
editor.loadProjectData(componentProjectData);
const components = editor.getComponents();
const component = components.models[0];
const style = component.getStyle();
expect(style).toEqual({
color: 'red',
});
});
test('TraitDataVariable', () => {
const componentProjectData: ProjectData = {
assets: [],
pages: [
{
frames: [
{
component: {
components: [
{
attributes: {
value: 'default',
},
'attributes-data-variable': {
value: {
path: 'test-input.id1.value',
type: 'data-variable',
value: 'default',
},
},
tagName: 'input',
void: true,
},
],
docEl: {
tagName: 'html',
},
head: {
type: 'head',
},
stylable: [
'background',
'background-color',
'background-image',
'background-repeat',
'background-attachment',
'background-position',
'background-size',
],
type: 'wrapper',
},
id: 'frameid',
},
],
id: 'pageid',
type: 'main',
},
],
styles: [],
symbols: [],
};
editor.loadProjectData(componentProjectData);
const components = editor.getComponents();
const component = components.models[0];
const value = component.getAttributes();
expect(value).toEqual({
value: 'test-value',
});
});
});
}); });

Loading…
Cancel
Save