From f94b40becc483d212186c5d8280c9258c258bc46 Mon Sep 17 00:00:00 2001 From: Mihaela Balutoiu Date: Mon, 23 Mar 2026 10:30:23 +0200 Subject: [PATCH 1/3] Fix `integer fields` with accepted values not rendering as `dropdowns` Signed-off-by: Mihaela Balutoiu --- src/@types/Endpoint.ts | 7 ++++-- src/components/ui/FieldInput/FieldInput.tsx | 13 ++++++++++- src/plugins/default/OptionsSchemaPlugin.ts | 24 +++++++++++++-------- src/stores/WizardStore.ts | 2 +- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/@types/Endpoint.ts b/src/@types/Endpoint.ts index f7f31572..176de70a 100644 --- a/src/@types/Endpoint.ts +++ b/src/@types/Endpoint.ts @@ -43,8 +43,11 @@ export type MultiValidationItem = { export type OptionValues = { name: string; - values: string[] | { name: string; id: string; [prop: string]: any }[]; - config_default: string | { name: string; id: string }; + values: + | string[] + | number[] + | { name: string; id: string; [prop: string]: any }[]; + config_default: string | number | { name: string; id: string }; }; export type StorageBackend = { diff --git a/src/components/ui/FieldInput/FieldInput.tsx b/src/components/ui/FieldInput/FieldInput.tsx index d7c66a0a..7889ce00 100644 --- a/src/components/ui/FieldInput/FieldInput.tsx +++ b/src/components/ui/FieldInput/FieldInput.tsx @@ -288,6 +288,14 @@ class FieldInput extends React.Component { return e; } + if (typeof e === "number") { + return { + label: String(e), + value: e, + disabled: false, + subtitleLabel: "", + }; + } return { label: typeof e === "string" @@ -295,7 +303,7 @@ class FieldInput extends React.Component { ? LabelDictionary.get(e) : e : e.name || e.label, - value: typeof e === "string" ? e : e.id || e.value, + value: typeof e === "string" ? e : (e.id ?? e.value), disabled: typeof e !== "string" ? Boolean(e.disabled) : false, subtitleLabel: typeof e !== "string" ? e.subtitleLabel || "" : false, }; @@ -441,6 +449,9 @@ class FieldInput extends React.Component { } return this.renderTextInput(); case "integer": + if (this.props.enum && this.props.enum.length) { + return this.renderEnumDropdown(this.props.enum); + } return this.renderIntInput(); case "radio": return this.renderRadioInput(); diff --git a/src/plugins/default/OptionsSchemaPlugin.ts b/src/plugins/default/OptionsSchemaPlugin.ts index 33ca14f5..0c8a85e8 100644 --- a/src/plugins/default/OptionsSchemaPlugin.ts +++ b/src/plugins/default/OptionsSchemaPlugin.ts @@ -14,7 +14,7 @@ along with this program. If not, see . import Utils from "@src/utils/ObjectUtils"; -import { Field, isEnumSeparator } from "@src/@types/Field"; +import { Field, EnumItem, isEnumSeparator } from "@src/@types/Field"; import type { OptionValues, StorageMap } from "@src/@types/Endpoint"; import type { SchemaProperties, SchemaDefinitions } from "@src/@types/Schema"; import type { NetworkMap } from "@src/@types/Network"; @@ -27,16 +27,18 @@ const migrationImageOsTypes = ["windows", "linux"]; export const defaultFillFieldValues = (field: Field, option: OptionValues) => { if (field.type === "string") { - field.enum = [...option.values]; + field.enum = [...option.values] as EnumItem[]; if (option.config_default) { field.default = typeof option.config_default === "string" ? option.config_default - : option.config_default.id; + : typeof option.config_default === "object" + ? option.config_default.id + : String(option.config_default); } } if (field.type === "array") { - field.enum = [...option.values]; + field.enum = [...option.values] as EnumItem[]; } if (field.type === "boolean" && option.config_default != null) { field.default = @@ -44,11 +46,15 @@ export const defaultFillFieldValues = (field: Field, option: OptionValues) => { ? option.config_default : option.config_default === "true"; } - if ( - (field.type === "integer" || field.type === "number") && - option.config_default != null - ) { - field.default = Number(option.config_default); + if (field.type === "integer" || field.type === "number") { + if (option.values?.length) { + field.enum = option.values.map(v => + typeof v === "number" ? { label: String(v), value: v } : v, + ) as EnumItem[]; + } + if (option.config_default != null) { + field.default = Number(option.config_default); + } } }; diff --git a/src/stores/WizardStore.ts b/src/stores/WizardStore.ts index 4f12966b..0f82bae5 100644 --- a/src/stores/WizardStore.ts +++ b/src/stores/WizardStore.ts @@ -122,7 +122,7 @@ class WizardStore { } return enumItem.id != null ? enumItem.id === fieldDefault || enumItem.name === fieldDefault - : enumItem === fieldDefault; + : enumItem === fieldDefault || enumItem.value === fieldDefault; }); // Don't use the default if it can't be found in the enum list. From c5821d455eb7e473d9192eb4148c33db294237ad Mon Sep 17 00:00:00 2001 From: Mihaela Balutoiu Date: Wed, 25 Mar 2026 10:13:02 +0200 Subject: [PATCH 2/3] Fix `Stepper` clearing field value on blur when no input was typed Signed-off-by: Mihaela Balutoiu --- src/components/ui/Stepper/Stepper.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/ui/Stepper/Stepper.tsx b/src/components/ui/Stepper/Stepper.tsx index ed660cc7..f1689180 100644 --- a/src/components/ui/Stepper/Stepper.tsx +++ b/src/components/ui/Stepper/Stepper.tsx @@ -159,7 +159,9 @@ class Stepper extends React.Component { } handleInputBlur() { - this.commitChange(this.state.inputValue || ""); + if (this.state.inputValue !== null) { + this.commitChange(this.state.inputValue); + } this.setState({ inputValue: null }); } From 41e937ac7c0986fb5baecf93af41471125f6110b Mon Sep 17 00:00:00 2001 From: Mihaela Balutoiu Date: Wed, 25 Mar 2026 13:38:25 +0200 Subject: [PATCH 3/3] Fix `object` fields with sub-properties missing from `LabelDictionary` cache Signed-off-by: Mihaela Balutoiu --- src/plugins/default/ConnectionSchemaPlugin.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plugins/default/ConnectionSchemaPlugin.ts b/src/plugins/default/ConnectionSchemaPlugin.ts index b309540e..abe154de 100644 --- a/src/plugins/default/ConnectionSchemaPlugin.ts +++ b/src/plugins/default/ConnectionSchemaPlugin.ts @@ -52,9 +52,19 @@ export const defaultSchemaToFields = ( properties.properties && Object.keys(properties.properties).length ) { + LabelDictionary.pushToCache( + { + name: fieldName, + title: properties.title, + description: properties.description, + }, + dictionaryKey || "", + ); return { name: fieldName, type: "object", + title: properties.title, + description: properties.description, properties: defaultSchemaToFields(properties, null, dictionaryKey), }; }