Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: add missing import statement, and correct controlled component s…
Browse files Browse the repository at this point in the history
…tate tracking (#374)
alharris-at committed Feb 25, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 053966d commit fe703f9
Showing 11 changed files with 112 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -5167,6 +5167,7 @@ import {
EscapeHatchProps,
getOverrideProps,
useDataStoreUpdateAction,
useStateMutationAction,
} from \\"@aws-amplify/ui-react/internal\\";
import { Button, Flex, FlexProps, TextField } from \\"@aws-amplify/ui-react\\";
import { Customer } from \\"../models\\";
@@ -5191,7 +5192,9 @@ export default function MyForm(props: MyFormProps): React.ReactElement {
<TextField
label=\\"Username\\"
value={usernameTextFieldValue}
onChange={setUsernameTextFieldValue}
onChange={(event: SyntheticEvent) => {
setUsernameTextFieldValue(event.target.value);
}}
{...getOverrideProps(overrides, \\"UsernameTextField\\")}
></TextField>
<Button
@@ -5217,6 +5220,7 @@ import React from \\"react\\";
import {
EscapeHatchProps,
getOverrideProps,
useStateMutationAction,
} from \\"@aws-amplify/ui-react/internal\\";
import { Button, Flex, FlexProps } from \\"@aws-amplify/ui-react\\";

12 changes: 12 additions & 0 deletions packages/codegen-ui-react/lib/imports/import-mapping.ts
Original file line number Diff line number Diff line change
@@ -32,6 +32,12 @@ export enum ImportValue {
USE_DATA_STORE_BINDING = 'useDataStoreBinding',
CREATE_THEME = 'createTheme',
MERGE_VARIANTS_OVERRIDES = 'mergeVariantsAndOverrides',
USE_NAVIGATE_ACTION = 'useNavigateAction',
USE_DATA_STORE_CREATE_ACTION = 'useDataStoreCreateAction',
USE_DATA_STORE_UPDATE_ACTION = 'useDataStoreUpdateAction',
USE_DATA_STORE_DELETE_ACTION = 'useDataStoreDeleteAction',
USE_AUTH_SIGN_OUT_ACTION = 'useAuthSignOutAction',
USE_STATE_MUTATION_ACTION = 'useStateMutationAction',
}

export const ImportMapping: Record<ImportValue, ImportSource> = {
@@ -46,4 +52,10 @@ export const ImportMapping: Record<ImportValue, ImportSource> = {
[ImportValue.SORT_DIRECTION]: ImportSource.AMPLIFY_DATASTORE,
[ImportValue.SORT_PREDICATE]: ImportSource.AMPLIFY_DATASTORE,
[ImportValue.MERGE_VARIANTS_OVERRIDES]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_NAVIGATE_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_DATA_STORE_CREATE_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_DATA_STORE_UPDATE_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_DATA_STORE_DELETE_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_AUTH_SIGN_OUT_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_STATE_MUTATION_ACTION]: ImportSource.UI_REACT_INTERNAL,
};
11 changes: 7 additions & 4 deletions packages/codegen-ui-react/lib/react-component-renderer.ts
Original file line number Diff line number Diff line change
@@ -34,7 +34,11 @@ import {
getStateName,
getSetStateName,
} from './react-component-render-helper';
import { buildOpeningElementEvents, filterStateReferencesForComponent } from './workflow';
import {
buildOpeningElementControlEvents,
buildOpeningElementEvents,
filterStateReferencesForComponent,
} from './workflow';
import { ImportCollection, ImportSource, ImportValue } from './imports';

export class ReactComponentRenderer<TPropIn> extends ComponentRendererBase<
@@ -78,10 +82,9 @@ export class ReactComponentRenderer<TPropIn> extends ComponentRendererBase<
const controlEventAttributes = Object.entries(localStateReferences)
.filter(([, { addControlEvent }]) => addControlEvent)
.map(([key]) =>
buildOpeningElementEvents(
{ bindingEvent: getSetStateName({ componentName: this.component.name || '', property: key }) },
buildOpeningElementControlEvents(
getSetStateName({ componentName: this.component.name || '', property: key }),
'change', // TODO: use component event mapping
this.component.name,
),
);
const attributes = propertyAttributes.concat(eventAttributes).concat(controlEventAttributes);
Original file line number Diff line number Diff line change
@@ -28,7 +28,11 @@ import {
getStateName,
getSetStateName,
} from './react-component-render-helper';
import { buildOpeningElementEvents, filterStateReferencesForComponent } from './workflow';
import {
buildOpeningElementControlEvents,
buildOpeningElementEvents,
filterStateReferencesForComponent,
} from './workflow';
import Primitive, { PrimitiveChildrenPropMapping } from './primitive';

export class ReactComponentWithChildrenRenderer<TPropIn> extends ComponentWithChildrenRendererBase<
@@ -76,10 +80,9 @@ export class ReactComponentWithChildrenRenderer<TPropIn> extends ComponentWithCh
const controlEventAttributes = Object.entries(localStateReferences)
.filter(([, { addControlEvent }]) => addControlEvent)
.map(([key]) =>
buildOpeningElementEvents(
{ bindingEvent: getSetStateName({ componentName: this.component.name || '', property: key }) },
buildOpeningElementControlEvents(
getSetStateName({ componentName: this.component.name || '', property: key }),
'change', // TODO: use component event mapping
this.component.name,
),
);
const attributes = propertyAttributes.concat(eventAttributes).concat(controlEventAttributes);
Original file line number Diff line number Diff line change
@@ -590,7 +590,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer
statements.push(this.buildOverridesFromVariantsAndProp());
}

const stateStatements = buildStateStatements(component, this.stateReferences);
const stateStatements = buildStateStatements(component, this.stateReferences, this.importCollection);
stateStatements.forEach((entry) => {
statements.push(entry);
});
24 changes: 12 additions & 12 deletions packages/codegen-ui-react/lib/workflow/action.ts
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ import {
MutationAction,
} from '@aws-amplify/codegen-ui';
import { isActionEvent, propertyToExpression, getSetStateName } from '../react-component-render-helper';
import { ImportCollection, ImportSource } from '../imports';
import { ImportCollection, ImportSource, ImportValue } from '../imports';

enum Action {
'Amplify.Navigate' = 'Amplify.Navigate',
@@ -37,13 +37,13 @@ enum Action {

export default Action;

export const ActionNameMapping: Partial<Record<Action, string>> = {
[Action['Amplify.Navigate']]: 'useNavigateAction',
[Action['Amplify.DataStoreCreateItem']]: 'useDataStoreCreateAction',
[Action['Amplify.DataStoreUpdateItem']]: 'useDataStoreUpdateAction',
[Action['Amplify.DataStoreDeleteItem']]: 'useDataStoreDeleteAction',
[Action['Amplify.AuthSignOut']]: 'useAuthSignOutAction',
[Action['Amplify.Mutation']]: 'useStateMutationAction',
export const ActionNameMapping: Partial<Record<Action, ImportValue>> = {
[Action['Amplify.Navigate']]: ImportValue.USE_NAVIGATE_ACTION,
[Action['Amplify.DataStoreCreateItem']]: ImportValue.USE_DATA_STORE_CREATE_ACTION,
[Action['Amplify.DataStoreUpdateItem']]: ImportValue.USE_DATA_STORE_UPDATE_ACTION,
[Action['Amplify.DataStoreDeleteItem']]: ImportValue.USE_DATA_STORE_DELETE_ACTION,
[Action['Amplify.AuthSignOut']]: ImportValue.USE_AUTH_SIGN_OUT_ACTION,
[Action['Amplify.Mutation']]: ImportValue.USE_STATE_MUTATION_ACTION,
};

export function isAction(action: string): action is Action {
@@ -54,7 +54,7 @@ export function isMutationAction(action: ActionStudioComponentEvent): action is
return (action.action as Action) === Action['Amplify.Mutation'];
}

export function getActionHookName(action: string): string {
export function getActionHookImportValue(action: string): ImportValue {
const actionName = ActionNameMapping[Action[action as Action]];
if (actionName === undefined) {
throw new InvalidInputError(`${action} is not a valid action.`);
@@ -95,8 +95,8 @@ export function buildUseActionStatement(
return buildMutationActionStatement(action, identifier);
}

const actionHookName = getActionHookName(action.action);
importCollection.addImport(ImportSource.UI_REACT_INTERNAL, actionHookName);
const actionHookImportValue = getActionHookImportValue(action.action);
importCollection.addMappedImport(actionHookImportValue);
return factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
@@ -105,7 +105,7 @@ export function buildUseActionStatement(
factory.createIdentifier(identifier),
undefined,
undefined,
factory.createCallExpression(factory.createIdentifier(actionHookName), undefined, [
factory.createCallExpression(factory.createIdentifier(actionHookImportValue), undefined, [
buildActionParameters(action, importCollection),
]),
),
56 changes: 54 additions & 2 deletions packages/codegen-ui-react/lib/workflow/mutation.ts
Original file line number Diff line number Diff line change
@@ -13,13 +13,14 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
import ts, { Statement, factory } from 'typescript';
import ts, { Statement, factory, JsxAttribute } from 'typescript';
import {
StudioComponent,
StudioComponentChild,
StateStudioComponentProperty,
ActionStudioComponentEvent,
StateReference,
StudioGenericEvent,
} from '@aws-amplify/codegen-ui';
import {
isActionEvent,
@@ -29,6 +30,8 @@ import {
getStateName,
getSetStateName,
} from '../react-component-render-helper';
import { ImportCollection, ImportValue } from '../imports';
import { mapGenericEventToReact } from './events';

export function getComponentStateReferences(component: StudioComponent | StudioComponentChild) {
const stateReferences: StateReference[] = [];
@@ -75,7 +78,56 @@ export function getActionStateParameters(action: ActionStudioComponentEvent): St
return [];
}

export function buildStateStatements(component: StudioComponent, stateReferences: StateReference[]): Statement[] {
export function buildOpeningElementControlEvents(stateName: string, event: string): JsxAttribute {
return factory.createJsxAttribute(
factory.createIdentifier(mapGenericEventToReact(event as StudioGenericEvent)),
factory.createJsxExpression(
undefined,
factory.createArrowFunction(
undefined,
undefined,
[
factory.createParameterDeclaration(
undefined,
undefined,
undefined,
factory.createIdentifier('event'),
undefined,
factory.createTypeReferenceNode(factory.createIdentifier('SyntheticEvent'), undefined),
undefined,
),
],
undefined,
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
factory.createBlock(
[
factory.createExpressionStatement(
factory.createCallExpression(factory.createIdentifier(stateName), undefined, [
factory.createPropertyAccessExpression(
factory.createPropertyAccessExpression(
factory.createIdentifier('event'),
factory.createIdentifier('target'),
),
factory.createIdentifier('value'),
),
]),
),
],
false,
),
),
),
);
}

export function buildStateStatements(
component: StudioComponent,
stateReferences: StateReference[],
importCollection: ImportCollection,
): Statement[] {
if (stateReferences.length > 0) {
importCollection.addMappedImport(ImportValue.USE_STATE_MUTATION_ACTION);
}
return stateReferences.map((stateReference) => {
return factory.createVariableStatement(
undefined,
29 changes: 14 additions & 15 deletions packages/codegen-ui/example-schemas/workflow/authSignOutAction.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
{
"componentType": "Button",
"name": "SignOutButton",
"properties": {
"label": {
"value": "Sign out"
}
},
"events": {
"click": {
"action": "Amplify.AuthSignOut",
"parameters": {
"global": {
"value": false
}
"componentType": "Button",
"name": "SignOutButton",
"properties": {
"label": {
"value": "Sign out"
}
},
"events": {
"click": {
"action": "Amplify.AuthSignOut",
"parameters": {
"global": {
"value": false
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"componentType": "Button",
"name": "CreateCustomerButton",
"properties": {},
"events": {
"click": {
"action": "Amplify.DataStoreCreateItem",
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"componentType": "Button",
"name": "DeleteCustomerButton",
"properties": {},
"events": {
"click": {
"action": "Amplify.DataStoreDeleteItem",
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"componentType": "Button",
"name": "UpdateCustomerButton",
"properties": {},
"events": {
"click": {
"action": "Amplify.DataStoreUpdateItem",

0 comments on commit fe703f9

Please sign in to comment.