feat(nodes): add InputField.ui_choice_labels: dict[str, str]

This maps values to labels for multiple-choice fields.

This allows "enum" fields (i.e. `Literal["val1", "val2", ...]` fields) to use code-friendly string values for choices, but present this to the UI as human-friendly labels.
This commit is contained in:
psychedelicious 2023-09-13 16:24:22 +10:00
parent ec0f6e7248
commit 57ebf735e6
6 changed files with 215 additions and 35 deletions

View File

@ -198,6 +198,7 @@ class _InputField(BaseModel):
ui_type: Optional[UIType]
ui_component: Optional[UIComponent]
ui_order: Optional[int]
ui_choice_labels: Optional[dict[str, str]]
item_default: Optional[Any]
@ -246,6 +247,7 @@ def InputField(
ui_component: Optional[UIComponent] = None,
ui_hidden: bool = False,
ui_order: Optional[int] = None,
ui_choice_labels: Optional[dict[str, str]] = None,
item_default: Optional[Any] = None,
**kwargs: Any,
) -> Any:
@ -312,6 +314,7 @@ def InputField(
ui_hidden=ui_hidden,
ui_order=ui_order,
item_default=item_default,
ui_choice_labels=ui_choice_labels,
**kwargs,
)

View File

@ -35,7 +35,11 @@ const EnumInputFieldComponent = (
value={field.value}
>
{fieldTemplate.options.map((option) => (
<option key={option}>{option}</option>
<option key={option} value={option}>
{fieldTemplate.ui_choice_labels
? fieldTemplate.ui_choice_labels[option]
: option}
</option>
))}
</Select>
);

View File

@ -286,7 +286,7 @@ export type BooleanPolymorphicInputFieldValue = z.infer<
export const zEnumInputFieldValue = zInputFieldValueBase.extend({
type: z.literal('enum'),
value: z.union([z.string(), z.number()]).optional(),
value: z.string().optional(),
});
export type EnumInputFieldValue = z.infer<typeof zEnumInputFieldValue>;
@ -822,10 +822,10 @@ export type ControlPolymorphicInputFieldTemplate = Omit<
};
export type EnumInputFieldTemplate = InputFieldTemplateBase & {
default: string | number;
default: string;
type: 'enum';
enumType: 'string' | 'number';
options: Array<string | number>;
options: string[];
labels?: { [key: string]: string };
};
export type MainModelInputFieldTemplate = InputFieldTemplateBase & {

View File

@ -656,8 +656,8 @@ const buildEnumInputFieldTemplate = ({
const template: EnumInputFieldTemplate = {
...baseField,
type: 'enum',
enumType: (schemaObject.type as 'string' | 'number') ?? 'string', // TODO: dangerous?
options: options,
options,
ui_choice_labels: schemaObject.ui_choice_labels,
default: schemaObject.default ?? options[0],
};

View File

@ -1,8 +1,7 @@
import { InputFieldTemplate, InputFieldValue } from '../types/types';
const FIELD_VALUE_FALLBACK_MAP = {
'enum.number': 0,
'enum.string': '',
enum: '',
boolean: false,
BooleanCollection: [],
BooleanPolymorphic: false,
@ -62,19 +61,8 @@ export const buildInputFieldValue = (
fieldKind: 'input',
} as InputFieldValue;
if (template.type === 'enum') {
if (template.enumType === 'number') {
fieldValue.value =
template.default ?? FIELD_VALUE_FALLBACK_MAP['enum.number'];
}
if (template.enumType === 'string') {
fieldValue.value =
template.default ?? FIELD_VALUE_FALLBACK_MAP['enum.string'];
}
} else {
fieldValue.value =
template.default ?? FIELD_VALUE_FALLBACK_MAP[template.type];
}
return fieldValue;
};

File diff suppressed because one or more lines are too long