Skip to content

Commit

Permalink
Change BoolField, CheckBoxGroup and RadioField
Browse files Browse the repository at this point in the history
  • Loading branch information
ljmotta committed Dec 20, 2024
1 parent fdf929d commit 5124525
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ import { FormInput, InputReference } from "../api";

import { getInputReference, getStateCodeFromRef, renderField } from "./utils/Utils";
import { BOOLEAN } from "./utils/dataTypes";
import { getListItemName, getListItemOnChange, getListItemValue, ListItemProps } from "./rendering/ListItemField";

export type BoolFieldProps = HTMLFieldProps<
boolean,
HTMLDivElement,
{
name: string;
label: string;
itemProps?: ListItemProps;
}
>;

Expand All @@ -41,12 +43,12 @@ const Bool: React.FC<BoolFieldProps> = (props: BoolFieldProps) => {

const jsxCode = `<FormGroup fieldId='${props.id}'>
<Checkbox
isChecked={${ref.stateName}}
isChecked={${props.itemProps?.isListItem ? getListItemValue({ itemProps: props.itemProps, name: props.name }) : ref.stateName}}
isDisabled={${props.disabled || "false"}}
id={'${props.id}'}
name={'${props.name}'}
name={${props.itemProps?.isListItem ? getListItemName({ itemProps: props.itemProps, name: props.name }) : `'${props.name}'`}}
label={'${props.label}'}
onChange={${ref.stateSetter}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange({ itemProps: props.itemProps, name: props.name }) : ref.stateSetter}}
/>
</FormGroup>`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { FormInput, InputReference } from "../api";
import { useAddFormElementToContext } from "./CodeGenContext";
import { CHECKBOX_GROUP_FUNCTIONS } from "./staticCode/staticCodeBlocks";
import { ARRAY } from "./utils/dataTypes";
import { getListItemName, getListItemOnChange, getListItemValue, ListItemProps } from "./rendering/ListItemField";

export type CheckBoxGroupProps = HTMLFieldProps<
string[],
Expand All @@ -34,6 +35,7 @@ export type CheckBoxGroupProps = HTMLFieldProps<
allowedValues?: string[];
required: boolean;
transform?(value: string): string;
itemProps: ListItemProps;
}
>;

Expand All @@ -42,14 +44,18 @@ const CheckBoxGroup: React.FC<CheckBoxGroupProps> = (props: CheckBoxGroupProps)

const jsxCode = props.allowedValues
?.map((value) => {
return `<Checkbox key={'${props.id}-${value}'} id={'${props.id}-${value}'} name={'${props.name}'} aria-label={'${
props.name
}'}
label={'${props.transform ? props.transform(value) : value}'}
isDisabled={${props.disabled || false}}
isChecked={${ref.stateName}.indexOf('${value}') != -1}
onChange={() => handleCheckboxGroupChange('${value}', ${ref.stateName}, ${ref.stateSetter})}
value={'${value}'}/>`;
return `<Checkbox
key={'${props.id}-${value}'}
id={'${props.id}-${value}'}
name={${props.itemProps?.isListItem ? getListItemName({ itemProps: props.itemProps, name: props.name }) : `'${props.name}'`}}
aria-label={'${props.name}'}
label={'${props.transform ? props.transform(value) : value}'}
isDisabled={${props.disabled || false}}
isChecked={${ref.stateName}.indexOf('${value}') != -1}
onChange={() => handleCheckboxGroupChange('${value}', ${ref.stateName}, ${ref.stateSetter})}
value={${props.itemProps?.isListItem ? getListItemValue({ itemProps: props.itemProps, name: props.name }) : `'${value}'`}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange({ itemProps: props.itemProps, name: props.name, callback: (internalValue: string) => `handleCheckboxGroupChange('${internalValue}', ${ref.stateName}, ${ref.stateSetter})`, overrideNewValue: `'${value}'` }) : `handleCheckboxGroupChange('${value}', ${ref.stateName}, ${ref.stateSetter})`}}
/>`;
})
.join("\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const List: React.FC<ListFieldProps> = (props: ListFieldProps) => {
pfImports: [...new Set(["Split", "SplitItem", "Button", ...(listItem?.pfImports ?? [])])],
reactImports: [...new Set([...(listItem?.reactImports ?? [])])],
requiredCode: [...new Set([...(listItem?.requiredCode ?? [])])],
// requiredIcons: ["PlusCircleIcon", "MinusCircleIcon"],
jsxCode,
stateCode: getStateCode(ref.stateName, ref.stateSetter, "any[]", "[]"),
isReadonly: props.disabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ const Num: React.FC<NumFieldProps> = (props: NumFieldProps) => {

const inputJsxCode = `<TextInput
type={'number'}
name={${props.itemProps?.isListItem ? getListItemName(props.itemProps, props.name) : `'${props.name}'`}}
name={${props.itemProps?.isListItem ? getListItemName({ itemProps: props.itemProps, name: props.name }) : `'${props.name}'`}}
isDisabled={${props.disabled || "false"}}
id={'${props.id}'}
placeholder={'${props.placeholder}'}
step={${props.decimal ? 0.01 : 1}} ${max} ${min}
value={${props.itemProps?.isListItem ? getListItemValue(props.itemProps, props.name) : ref.stateName}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange(props.itemProps, props.name, (value: string) => `Number(${value})`) : `(newValue) => ${ref.stateSetter}(Number(newValue))`}}
value={${props.itemProps?.isListItem ? getListItemValue({ itemProps: props.itemProps, name: props.name }) : ref.stateName}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange({ itemProps: props.itemProps, name: props.name, callback: (value: string) => `Number(${value})` }) : `(newValue) => ${ref.stateSetter}(Number(newValue))`}}
/>`;

const element: FormInput = buildDefaultInputElement({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useAddFormElementToContext } from "./CodeGenContext";
import { FormInput, InputReference } from "../api";
import { buildDefaultInputElement, getInputReference, renderField } from "./utils/Utils";
import { STRING } from "./utils/dataTypes";
import { getListItemName, getListItemOnChange, getListItemValue, ListItemProps } from "./rendering/ListItemField";

export type RadioFieldProps = HTMLFieldProps<
string,
Expand All @@ -34,6 +35,7 @@ export type RadioFieldProps = HTMLFieldProps<
allowedValues: string[];
required: boolean;
disabled: boolean;
itemProps?: ListItemProps;
}
>;

Expand All @@ -46,12 +48,12 @@ const Radio = (props: RadioFieldProps) => {
const radio = `<Radio
key={'${item}'}
id={'${props.id}-${item}'}
name={'${props.name}'}
isChecked={'${item}' === ${ref.stateName}}
name={${props.itemProps?.isListItem ? getListItemName({ itemProps: props.itemProps, name: props.name }) : `'${props.name}'`}}
isChecked={${props.itemProps?.isListItem ? getListItemValue({ itemProps: props.itemProps, name: props.name }) : `'${item}' === ${ref.stateName}`}}
isDisabled={${props.disabled || false}}
label={'${props.transform ? props.transform(item) : item}'}
aria-label={'${props.name}'}
onChange={() => ${ref.stateSetter}('${item}')}
onChange={${props.itemProps?.isListItem ? getListItemOnChange({ itemProps: props.itemProps, name: props.name, overrideNewValue: item }) : `() => ${ref.stateSetter}('${item}')`}}
/>`;
radios.push(radio);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ const Text: React.FC<TextFieldProps> = (props: TextFieldProps) => {
const inputJsxCode = `<DatePicker
id={'date-picker-${props.id}'}
isDisabled={${props.disabled || false}}
name={${props.itemProps?.isListItem ? getListItemName(props.itemProps, props.name) : `'${props.name}'`}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange(props.itemProps, props.name, (value: string) => `onDateChange(${value}, ${ref.stateSetter}, ${ref.stateName})`) : `newDate => onDateChange(newDate, ${ref.stateSetter}, ${ref.stateName})`}}
value={${props.itemProps?.isListItem ? `parseDate(${getListItemValue(props.itemProps, props.name)})` : `parseDate(${ref.stateName})`}}
name={${props.itemProps?.isListItem ? getListItemName({ itemProps: props.itemProps, name: props.name }) : `'${props.name}'`}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange({ itemProps: props.itemProps, name: props.name, callback: (value: string) => `onDateChange(${value}, ${ref.stateSetter}, ${ref.stateName})` }) : `newDate => onDateChange(newDate, ${ref.stateSetter}, ${ref.stateName})`}}
value={${props.itemProps?.isListItem ? `parseDate(${getListItemValue({ itemProps: props.itemProps, name: props.name })})` : `parseDate(${ref.stateName})`}}
/>`;
return buildDefaultInputElement({
pfImports: ["DatePicker"],
Expand All @@ -66,13 +66,13 @@ const Text: React.FC<TextFieldProps> = (props: TextFieldProps) => {

const getTextInputElement = (): FormInput => {
const inputJsxCode = `<TextInput
name={${props.itemProps?.isListItem ? getListItemName(props.itemProps, props.name) : `'${props.name}'`}}
name={${props.itemProps?.isListItem ? getListItemName({ itemProps: props.itemProps, name: props.name }) : `'${props.name}'`}}
id={'${props.id}'}
isDisabled={${props.disabled || "false"}}
placeholder={'${props.placeholder}'}
type={'${props.type || "text"}'}
value={${props.itemProps?.isListItem ? getListItemValue(props.itemProps, props.name) : ref.stateName}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange(props.itemProps, props.name) : ref.stateSetter}}
value={${props.itemProps?.isListItem ? getListItemValue({ itemProps: props.itemProps, name: props.name }) : ref.stateName}}
onChange={${props.itemProps?.isListItem ? getListItemOnChange({ itemProps: props.itemProps, name: props.name }) : ref.stateSetter}}
/>`;

return buildDefaultInputElement({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function getItemNameAndWithIsNested(name: string) {
* `listName.$`
* `listName.${index}.itemName`
*/
export const getListItemName = (itemProps: ListItemProps, name: string) => {
export const getListItemName = ({ itemProps, name }: { itemProps: ListItemProps; name: string }) => {
const { itemName, isNested } = getItemNameAndWithIsNested(name);
return `\`${itemProps?.listName}${isNested ? `.$\{${itemProps?.indexVariableName}}.${itemName}` : `.$\{${itemProps?.indexVariableName}}`}\``;
};
Expand All @@ -55,7 +55,7 @@ export const getListItemName = (itemProps: ListItemProps, name: string) => {
* `listStateName[index]`
* `listStateName[index].itemName.`
*/
export const getListItemValue = (itemProps: ListItemProps, name: string) => {
export const getListItemValue = ({ itemProps, name }: { itemProps: ListItemProps; name: string }) => {
const { itemName, isNested } = getItemNameAndWithIsNested(name);
return `${itemProps?.listStateName}[${itemProps?.indexVariableName}]${isNested ? `.${itemName}` : ""}`;
};
Expand All @@ -73,9 +73,22 @@ export const getListItemValue = (itemProps: ListItemProps, name: string) => {
* return newState;
* );`
*/
export const getListItemOnChange = (itemProps: ListItemProps, name: string, callback?: (value: string) => string) => {
export const getListItemOnChange = ({
itemProps,
name,
callback,
overrideNewValue,
}: {
itemProps: ListItemProps;
name: string;
callback?: (value: string) => string;
overrideNewValue?: string;
}) => {
const { itemName, isNested } = getItemNameAndWithIsNested(name);
return `newValue => ${itemProps?.listStateSetter}(s => { const newState = [...s]; newState[${itemProps?.indexVariableName}]${isNested ? `.${itemName}` : ""} = newValue; return ${callback ? callback("newState") : "newState"}; })`;
return `
newValue => ${itemProps?.listStateSetter}(s => { const newState = [...s];
newState[${itemProps?.indexVariableName}]${isNested ? `.${itemName}` : ""} = ${callback ? callback(overrideNewValue ? overrideNewValue : "newValue") : overrideNewValue ? overrideNewValue : "newValue"};
return newState; })`;
};

export interface Props {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,18 @@ describe("<CheckBoxGroupField> tests", () => {
expect(formElement.jsxCode).toContain("isDisabled={false}");

props.allowedValues.forEach((value) => {
const checkbox = `<Checkbox key={'${props.id}-${value}'} id={'${props.id}-${value}'} name={'${props.name}'} aria-label={'${props.name}'}`;
const checkbox = `<Checkbox
key={'${props.id}-${value}'}
id={'${props.id}-${value}'}
name={'${props.name}'}
aria-label={'${props.name}'}`;
expect(formElement.jsxCode).toContain(checkbox);
expect(formElement.jsxCode).toContain(`label={'${value}'}`);
expect(formElement.jsxCode).toContain(`isChecked={${formElement.ref.stateName}.indexOf('${value}') != -1}`);
expect(formElement.jsxCode).toContain(
`onChange={() => handleCheckboxGroupChange('${value}', ${formElement.ref.stateName}, ${formElement.ref.stateSetter})}`
);
expect(formElement.jsxCode).toContain(`value={'${value}'}/>`);
expect(formElement.jsxCode).toContain(`value={'${value}'}`);
});
expect(formElement.stateCode).not.toBeNull();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ describe("<ListField> tests", () => {

const props: AutoFormProps = {
id: "id",
sanitizedId: "id",
schema: createSchema(schema),
disabled: false,
placeholder: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

exports[`<CheckBoxGroupField> tests <CheckBoxGroupField> - rendering 1`] = `
<div>
{"ref":{"binding":"roles","stateName":"roles","stateSetter":"set__roles","dataType":{"name":"string[]","defaultValue":"[]"}},"pfImports":["Checkbox","FormGroup"],"reactImports":["useState"],"requiredCode":["checkbox_group_functions"],"jsxCode":"&lt;FormGroup\\n fieldId={'id'}\\n label={'Roles'}\\n isRequired={true}\\n &gt;\\n &lt;Checkbox key={'id-Developer'} id={'id-Developer'} name={'roles'} aria-label={'roles'}\\n label={'Developer'} \\n isDisabled={false} \\n isChecked={roles.indexOf('Developer') != -1}\\n onChange={() =&gt; handleCheckboxGroupChange('Developer', roles, set__roles)}\\n value={'Developer'}/&gt;\\n&lt;Checkbox key={'id-HR'} id={'id-HR'} name={'roles'} aria-label={'roles'}\\n label={'HR'} \\n isDisabled={false} \\n isChecked={roles.indexOf('HR') != -1}\\n onChange={() =&gt; handleCheckboxGroupChange('HR', roles, set__roles)}\\n value={'HR'}/&gt;\\n&lt;Checkbox key={'id-UX'} id={'id-UX'} name={'roles'} aria-label={'roles'}\\n label={'UX'} \\n isDisabled={false} \\n isChecked={roles.indexOf('UX') != -1}\\n onChange={() =&gt; handleCheckboxGroupChange('UX', roles, set__roles)}\\n value={'UX'}/&gt;\\n &lt;/FormGroup&gt;","stateCode":"const [ roles, set__roles ] = useState&lt;string[]&gt;([]);","isReadonly":false}
{"ref":{"binding":"roles","stateName":"roles","stateSetter":"set__roles","dataType":{"name":"string[]","defaultValue":"[]"}},"pfImports":["Checkbox","FormGroup"],"reactImports":["useState"],"requiredCode":["checkbox_group_functions"],"jsxCode":"&lt;FormGroup\\n fieldId={'id'}\\n label={'Roles'}\\n isRequired={true}\\n &gt;\\n &lt;Checkbox\\n key={'id-Developer'}\\n id={'id-Developer'}\\n name={'roles'}\\n aria-label={'roles'}\\n label={'Developer'} \\n isDisabled={false} \\n isChecked={roles.indexOf('Developer') != -1}\\n onChange={() =&gt; handleCheckboxGroupChange('Developer', roles, set__roles)}\\n value={'Developer'}\\n onChange={handleCheckboxGroupChange('Developer', roles, set__roles)}\\n/&gt;\\n&lt;Checkbox\\n key={'id-HR'}\\n id={'id-HR'}\\n name={'roles'}\\n aria-label={'roles'}\\n label={'HR'} \\n isDisabled={false} \\n isChecked={roles.indexOf('HR') != -1}\\n onChange={() =&gt; handleCheckboxGroupChange('HR', roles, set__roles)}\\n value={'HR'}\\n onChange={handleCheckboxGroupChange('HR', roles, set__roles)}\\n/&gt;\\n&lt;Checkbox\\n key={'id-UX'}\\n id={'id-UX'}\\n name={'roles'}\\n aria-label={'roles'}\\n label={'UX'} \\n isDisabled={false} \\n isChecked={roles.indexOf('UX') != -1}\\n onChange={() =&gt; handleCheckboxGroupChange('UX', roles, set__roles)}\\n value={'UX'}\\n onChange={handleCheckboxGroupChange('UX', roles, set__roles)}\\n/&gt;\\n &lt;/FormGroup&gt;","stateCode":"const [ roles, set__roles ] = useState&lt;string[]&gt;([]);","isReadonly":false}
</div>
`;

0 comments on commit 5124525

Please sign in to comment.