Skip to content

Commit

Permalink
feat: add optional or required decorator on form labels (#936)
Browse files Browse the repository at this point in the history
Co-authored-by: Justin Shih <jushih@amazon.com>
  • Loading branch information
Jshhhh and Justin Shih authored Mar 14, 2023
1 parent 326b579 commit d81a50e
Show file tree
Hide file tree
Showing 23 changed files with 487 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3358,7 +3358,12 @@ export default function CustomDataForm(props) {
{...rest}
>
<TextField
label=\\"name\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>name</span>
<span style={{ color: \\"red\\" }}>*</span>
</span>
}
isRequired={true}
value={name}
onChange={(e) => {
Expand Down Expand Up @@ -3400,7 +3405,12 @@ export default function CustomDataForm(props) {
setCurrentEmailValue(\\"\\");
}}
currentFieldValue={currentEmailValue}
label={\\"E-mail\\"}
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>E-mail</span>
<span style={{ color: \\"red\\" }}>*</span>
</span>
}
items={email}
hasError={errors?.email?.hasError}
errorMessage={errors?.email?.errorMessage}
Expand Down Expand Up @@ -3444,7 +3454,12 @@ export default function CustomDataForm(props) {
setCurrentPhoneValue(\\"\\");
}}
currentFieldValue={currentPhoneValue}
label={\\"phone\\"}
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>phone</span>
<span style={{ color: \\"red\\" }}>*</span>
</span>
}
items={phone}
hasError={errors?.phone?.hasError}
errorMessage={errors?.phone?.errorMessage}
Expand Down Expand Up @@ -19977,7 +19992,15 @@ export default function InputGalleryCreateForm(props) {
{...rest}
>
<TextField
label=\\"Num\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Num</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isRequired={false}
isReadOnly={false}
type=\\"number\\"
Expand Down Expand Up @@ -20015,7 +20038,15 @@ export default function InputGalleryCreateForm(props) {
{...getOverrideProps(overrides, \\"num\\")}
></TextField>
<TextField
label=\\"Rootbeer\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Rootbeer</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isRequired={false}
isReadOnly={false}
type=\\"number\\"
Expand Down Expand Up @@ -20053,7 +20084,15 @@ export default function InputGalleryCreateForm(props) {
{...getOverrideProps(overrides, \\"rootbeer\\")}
></TextField>
<RadioGroupField
label=\\"Attend\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Attend</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
name=\\"attend\\"
isReadOnly={false}
isRequired=\\"false\\"
Expand Down Expand Up @@ -20098,7 +20137,15 @@ export default function InputGalleryCreateForm(props) {
></Radio>
</RadioGroupField>
<ToggleButton
children=\\"Maybe slide\\"
children={
<span style={{ display: \\"inline-flex\\" }}>
<span>Maybe Slide</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isDisabled={false}
defaultPressed={false}
isPressed={maybeSlide}
Expand Down Expand Up @@ -20132,7 +20179,15 @@ export default function InputGalleryCreateForm(props) {
{...getOverrideProps(overrides, \\"maybeSlide\\")}
></ToggleButton>
<CheckboxField
label=\\"Maybe check\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Maybe check</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
name=\\"maybeCheck\\"
value=\\"maybeCheck\\"
isDisabled={false}
Expand Down Expand Up @@ -20190,7 +20245,15 @@ export default function InputGalleryCreateForm(props) {
setCurrentArrayTypeFieldValue(\\"\\");
}}
currentFieldValue={currentArrayTypeFieldValue}
label={\\"Array type field\\"}
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Array type field</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
items={arrayTypeField}
hasError={errors?.arrayTypeField?.hasError}
errorMessage={errors?.arrayTypeField?.errorMessage}
Expand Down Expand Up @@ -20244,7 +20307,15 @@ export default function InputGalleryCreateForm(props) {
setCurrentJsonArrayValue(\\"\\");
}}
currentFieldValue={currentJsonArrayValue}
label={\\"Json array\\"}
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Json array</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
items={jsonArray}
hasError={errors?.jsonArray?.hasError}
errorMessage={errors?.jsonArray?.errorMessage}
Expand Down Expand Up @@ -20273,7 +20344,15 @@ export default function InputGalleryCreateForm(props) {
></TextAreaField>
</ArrayField>
<TextAreaField
label=\\"Json field\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Json field</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isRequired={false}
isReadOnly={false}
onChange={(e) => {
Expand Down Expand Up @@ -20306,7 +20385,15 @@ export default function InputGalleryCreateForm(props) {
{...getOverrideProps(overrides, \\"jsonField\\")}
></TextAreaField>
<TextField
label=\\"Timestamp\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Timestamp</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isRequired={false}
isReadOnly={false}
type=\\"datetime-local\\"
Expand Down Expand Up @@ -20342,7 +20429,15 @@ export default function InputGalleryCreateForm(props) {
{...getOverrideProps(overrides, \\"timestamp\\")}
></TextField>
<TextField
label=\\"Ippy\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Ippy</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isRequired={false}
isReadOnly={false}
value={ippy}
Expand Down Expand Up @@ -20376,7 +20471,15 @@ export default function InputGalleryCreateForm(props) {
{...getOverrideProps(overrides, \\"ippy\\")}
></TextField>
<TextField
label=\\"Timeisnow\\"
label={
<span style={{ display: \\"inline-flex\\" }}>
<span>Timeisnow</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
}
isRequired={false}
isReadOnly={false}
type=\\"time\\"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ export { buildRelationshipQuery, buildGetRelationshipModels } from './relationsh
export { shouldWrapInArrayField } from './render-checkers';

export { renderArrayFieldComponent } from './render-array-field';

export { getDecoratedLabel } from './label-decorator';
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { LabelDecorator, StudioComponentProperty } from '@aws-amplify/codegen-ui/lib/types';
import { factory } from 'typescript';

/**
<span style={{ display: \\"inline-flex\\" }}>
<span>City</span>
<span style={{ whiteSpace: \\"pre\\", fontStyle: \\"italic\\" }}>
{\\" \\"}
- optional
</span>
</span>
*/

export const getDecoratedLabel = (attribute: string, value: string, labelDecorator: LabelDecorator) =>
factory.createJsxAttribute(
factory.createIdentifier(attribute),
factory.createJsxExpression(
undefined,
factory.createJsxElement(
factory.createJsxOpeningElement(
factory.createIdentifier('span'),
undefined,
factory.createJsxAttributes([
factory.createJsxAttribute(
factory.createIdentifier('style'),
factory.createJsxExpression(
undefined,
factory.createObjectLiteralExpression(
[
factory.createPropertyAssignment(
factory.createIdentifier('display'),
factory.createStringLiteral('inline-flex'),
),
],
false,
),
),
),
]),
),
[
factory.createJsxElement(
factory.createJsxOpeningElement(
factory.createIdentifier('span'),
undefined,
factory.createJsxAttributes([]),
),
[factory.createJsxText(value, false)],
factory.createJsxClosingElement(factory.createIdentifier('span')),
),
generateLabelDecorator(labelDecorator),
],
factory.createJsxClosingElement(factory.createIdentifier('span')),
),
),
);

const generateLabelDecorator = (labelDecorator: LabelDecorator) => {
let styles = [
factory.createPropertyAssignment(factory.createIdentifier('whiteSpace'), factory.createStringLiteral('pre')),
factory.createPropertyAssignment(factory.createIdentifier('fontStyle'), factory.createStringLiteral('italic')),
];
let decoratorText = ' - optional';

if (labelDecorator === 'required') {
styles = [factory.createPropertyAssignment(factory.createIdentifier('color'), factory.createStringLiteral('red'))];
decoratorText = '*';
}

return factory.createJsxElement(
factory.createJsxOpeningElement(
factory.createIdentifier('span'),
undefined,
factory.createJsxAttributes([
factory.createJsxAttribute(
factory.createIdentifier('style'),
factory.createJsxExpression(undefined, factory.createObjectLiteralExpression(styles, false)),
),
]),
),
[factory.createJsxText(decoratorText, false)],
factory.createJsxClosingElement(factory.createIdentifier('span')),
);
};

export const getIsRequiredValue = (isRequiredProperty: StudioComponentProperty) => {
let isRequired = false;
if (isRequiredProperty && 'value' in isRequiredProperty) {
const isRequiredValue = isRequiredProperty.value;
if (typeof isRequiredValue === 'string') {
isRequired = isRequiredProperty.value === 'true';
}
}
return isRequired;
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
import { FieldConfigMetadata } from '@aws-amplify/codegen-ui';
import { FieldConfigMetadata, LabelDecorator } from '@aws-amplify/codegen-ui';
import { Expression, factory, Identifier, JsxAttribute, JsxChild, NodeFlags, SyntaxKind } from 'typescript';
import {
buildAccessChain,
Expand All @@ -29,6 +29,7 @@ import { isModelDataType, shouldImplementDisplayValueFunction } from './render-c
import { getDisplayValueObjectName } from './model-values';
import { getElementAccessExpression } from './invalid-variable-helpers';
import { getSetNameIdentifier, capitalizeFirstLetter } from '../../helpers';
import { getDecoratedLabel } from './label-decorator';

function getOnChangeAttribute({
setStateName,
Expand Down Expand Up @@ -127,6 +128,8 @@ export const renderArrayFieldComponent = (
fieldLabel: string,
fieldConfigs: Record<string, FieldConfigMetadata>,
inputField: JsxChild,
labelDecorator?: LabelDecorator,
isRequired?: boolean,
) => {
const fieldConfig = fieldConfigs[fieldName];
const { sanitizedFieldName, dataType, componentType } = fieldConfig;
Expand Down Expand Up @@ -168,16 +171,20 @@ export const renderArrayFieldComponent = (
}

props.push(getOnChangeAttribute({ fieldName, isLimitedToOneValue, fieldConfigs, renderedFieldName, setStateName }));
let labelAttribute = factory.createJsxAttribute(
factory.createIdentifier('label'),
factory.createJsxExpression(undefined, factory.createStringLiteral(fieldLabel)),
);

if ((labelDecorator === 'required' && isRequired) || (labelDecorator === 'optional' && !isRequired)) {
labelAttribute = getDecoratedLabel('label', fieldLabel, labelDecorator);
}
props.push(
factory.createJsxAttribute(
factory.createIdentifier(`currentFieldValue`),
factory.createIdentifier('currentFieldValue'),
factory.createJsxExpression(undefined, stateName),
),
factory.createJsxAttribute(
factory.createIdentifier(`label`),
factory.createJsxExpression(undefined, factory.createStringLiteral(fieldLabel)),
),
labelAttribute,
);

props.push(
Expand Down
Loading

0 comments on commit d81a50e

Please sign in to comment.