Skip to content

Commit

Permalink
fix: add data binding model imports (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpilch committed Sep 8, 2021
1 parent 5d95386 commit 11e5c47
Show file tree
Hide file tree
Showing 10 changed files with 932 additions and 8 deletions.
797 changes: 797 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ export default function BoxWithButton(props: BoxWithButtonProps): JSX.Element {
}"
`;

exports[`amplify render tests component with data binding should add model imports 1`] = `
"/* eslint-disable */
import React from \\"react\\";
import { User } from \\"../models\\";
import { Button, EscapeHatchProps, getOverrideProps } from \\"@aws-amplify/ui-react\\";
export type ComponentWithDataBindingProps = {
width: Number;
isDisabled: Boolean;
buttonUser?: User;
buttonColor: String;
} & {
overrides?: EscapeHatchProps | undefined | null;
};
export default function ComponentWithDataBinding(props: ComponentWithDataBindingProps): JSX.Element {
return (<Button label={buttonUser.username || \\"hspain@gmail.com\\"} labelWidth={width} disabled={isDisabled} {...props} {...getOverrideProps(props.overrides, \\"Button\\")}></Button>);
}"
`;

exports[`amplify render tests sample code snippet tests should generate a sample code snippet for components 1`] = `
"/* eslint-disable */
import React from \\"react\\";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,11 @@ describe('amplify render tests', () => {
expect(generatedCode).toMatchSnapshot();
});
});

describe('component with data binding', () => {
it('should add model imports', () => {
const generatedCode = generateWithAmplifyRenderer('componentWithDataBinding');
expect(generatedCode).toMatchSnapshot();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"id": "1234-5678-9010",
"componentType": "Button",
"name": "ComponentWithDataBinding",
"bindingProperties": {
"width": {
"type": "Number"
},
"isDisabled": {
"type": "Boolean"
},
"buttonUser": {
"type": "Data",
"bindingProperties": {
"model": "User"
}
},
"buttonColor": {
"type": "String"
}
},
"properties": {
"label": {
"bindingProperties": {
"property": "buttonUser",
"field": "username"
},
"defaultValue": "hspain@gmail.com"
},
"labelWidth": {
"bindingProperties": {
"property": "width"
}
},
"disabled": {
"bindingProperties": {
"property": "isDisabled"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import {
CollectionStudioComponentProperty,
WorkflowStudioComponentProperty,
FormStudioComponentProperty,
StudioComponent,
StudioComponentChild,
} from '@amzn/amplify-ui-codegen-schema';

import { factory, JsxAttribute, JsxExpression, StringLiteral, SyntaxKind } from 'typescript';

import { ImportCollection } from './import-collection';

export function getFixedComponentPropValueExpression(prop: FixedStudioComponentProperty): StringLiteral {
return factory.createStringLiteral(prop.value.toString(), true);
}
Expand Down Expand Up @@ -183,3 +187,16 @@ export function buildCollectionBindingAttrWithDefault(
);
return attr;
}

export function addBindingPropertiesImports(
component: StudioComponent | StudioComponentChild,
importCollection: ImportCollection,
) {
if ('bindingProperties' in component) {
Object.entries(component.bindingProperties).forEach(([property, binding]) => {
if ('bindingProperties' in binding && 'model' in binding.bindingProperties) {
importCollection.addImport('../models', binding.bindingProperties.model);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { StudioComponent, StudioComponentChild, StudioComponentProperties } from
import { ComponentRendererBase } from '@amzn/studio-ui-codegen';
import { JsxAttribute, JsxAttributeLike, JsxElement, JsxOpeningElement, NodeFactory } from 'typescript';

import { addBindingPropertiesImports, buildOpeningElementAttributes } from './react-component-render-helper';
import { ImportCollection } from './import-collection';
import { buildOpeningElementAttributes } from './react-component-render-helper';

export abstract class ReactComponentRenderer<TPropIn> extends ComponentRendererBase<TPropIn, JsxElement> {
constructor(component: StudioComponent | StudioComponentChild, protected importCollection: ImportCollection) {
super(component);
addBindingPropertiesImports(component, importCollection);
}

protected renderOpeningElement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
Expression,
} from 'typescript';
import { ImportCollection } from './import-collection';
import { buildOpeningElementAttributes } from './react-component-render-helper';
import { addBindingPropertiesImports, buildOpeningElementAttributes } from './react-component-render-helper';

export abstract class ReactComponentWithChildrenRenderer<TPropIn> extends ComponentWithChildrenRendererBase<
TPropIn,
Expand All @@ -21,6 +21,7 @@ export abstract class ReactComponentWithChildrenRenderer<TPropIn> extends Compon
> {
constructor(component: StudioComponent | StudioComponentChild, protected importCollection: ImportCollection) {
super(component);
addBindingPropertiesImports(component, importCollection);
}

protected renderCustomCompOpeningElement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,22 +243,21 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer
return factory.createTypeLiteralNode([]);
}
for (let bindingProp of Object.entries(component.bindingProperties)) {
const propName = bindingProp[0];
const typeName = bindingProp[1].type.toString();
if (isSimplePropertyBinding(bindingProp[1])) {
const [propName, binding] = bindingProp;
if (isSimplePropertyBinding(binding)) {
const propSignature = factory.createPropertySignature(
undefined,
propName,
undefined,
factory.createTypeReferenceNode(typeName, undefined),
factory.createTypeReferenceNode(binding.type, undefined),
);
propSignatures.push(propSignature);
} else if (isDataPropertyBinding(bindingProp[1])) {
} else if (isDataPropertyBinding(binding)) {
const propSignature = factory.createPropertySignature(
undefined,
propName,
factory.createToken(SyntaxKind.QuestionToken),
factory.createTypeReferenceNode(typeName, undefined),
factory.createTypeReferenceNode(binding.bindingProperties.model, undefined),
);
propSignatures.push(propSignature);
}
Expand Down
41 changes: 41 additions & 0 deletions packages/test-generator/lib/componentWithDataBinding.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"id": "1234-5678-9010",
"componentType": "Button",
"name": "ComponentWithDataBinding",
"bindingProperties": {
"width": {
"type": "Number"
},
"isDisabled": {
"type": "Boolean"
},
"buttonUser": {
"type": "Data",
"bindingProperties": {
"model": "User"
}
},
"buttonColor": {
"type": "String"
}
},
"properties": {
"label": {
"bindingProperties": {
"property": "buttonUser",
"field": "username"
},
"defaultValue": "hspain@gmail.com"
},
"labelWidth": {
"bindingProperties": {
"property": "width"
}
},
"disabled": {
"bindingProperties": {
"property": "isDisabled"
}
}
}
}
1 change: 1 addition & 0 deletions packages/test-generator/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { default as HeaderWithAction } from './headerWithAction.json';
export { default as SampleCodeSnippet } from './sampleCodeSnippet.json';
export { default as TextGolden } from './textGolden.json';
export { default as CollectionWithBinding } from './collectionWithBinding.json';
export { default as ComponentWithDataBinding } from './componentWithDataBinding.json';

0 comments on commit 11e5c47

Please sign in to comment.