diff --git a/e2e/playwright/tests/smoke-test/test.spec.ts b/e2e/playwright/tests/smoke-test/test.spec.ts index 9e87a4130a..c9d375b5cd 100644 --- a/e2e/playwright/tests/smoke-test/test.spec.ts +++ b/e2e/playwright/tests/smoke-test/test.spec.ts @@ -61,6 +61,12 @@ test('smoke test', async ({ page }) => { await page.getByRole('link', { name: 'Config', exact: true }).click(); await expect(page.locator('h3')).toContainText('My Example Config'); await expect(page.locator('#version_sequence-group')).toContainText('This version is 1'); + await expect(page.getByRole("combobox")).toHaveValue("option_1"); + await page.getByRole("combobox").selectOption("option_2"); + await expect(page.getByRole("combobox")).toHaveValue("option_2"); + await expect(page.getByLabel("radio_1")).toBeChecked(); + await page.getByLabel("radio_2").click(); + await expect(page.getByLabel("radio_2")).toBeChecked(); await expect(page.getByRole('button', { name: 'Save config' })).toBeVisible(); await page.getByRole('link', { name: 'Troubleshoot' }).click(); await expect(page.getByRole('button', { name: 'Analyze App Name' })).toBeVisible(); diff --git a/pkg/kotsadmconfig/types/types.go b/pkg/kotsadmconfig/types/types.go index 69f9d89b94..a98db125f5 100644 --- a/pkg/kotsadmconfig/types/types.go +++ b/pkg/kotsadmconfig/types/types.go @@ -10,6 +10,8 @@ const ( PasswordItemType = "password" TextAreaItemType = "textarea" SelectOneItemType = "select_one" + RadioItemType = "radio" + DropdownItemType = "dropdown" ) type ConfigGroupValidationError struct { diff --git a/pkg/template/config_context.go b/pkg/template/config_context.go index 17fdabd9d7..908b58bdda 100644 --- a/pkg/template/config_context.go +++ b/pkg/template/config_context.go @@ -205,6 +205,8 @@ func isReadOnly(item kotsv1beta1.ConfigItem) bool { "select": {}, "select_many": {}, "select_one": {}, + "radio": {}, + "dropdown": {}, "text": {}, "textarea": {}, } diff --git a/web/src/components/config_render/ConfigDropdown.tsx b/web/src/components/config_render/ConfigDropdown.tsx new file mode 100644 index 0000000000..bab9db5c28 --- /dev/null +++ b/web/src/components/config_render/ConfigDropdown.tsx @@ -0,0 +1,81 @@ +import { useState } from "react"; +import { ConfigWrapper } from "./ConfigComponents"; +import ConfigItemTitle from "./ConfigItemTitle"; +import Icon from "@components/Icon"; +import Markdown from "react-remarkable"; +import { isEmpty } from "lodash"; + +const ConfigDropdown = (props) => { + const [selectedValue, setSelectedValue] = useState( + props.value || props.default || "" + ); + + let options = [{ value: "", label: "Select an option" }]; + + props.items.map((item) => { + if (isEmpty(item)) { + return null; + } + options.push({ value: item.name, label: item.title }); + }); + + const handleChange = (val) => { + setSelectedValue(val); + props.handleOnChange(props.name, val); + }; + + return ( + + ); +}; + +export default ConfigDropdown; diff --git a/web/src/components/config_render/ConfigGroup.jsx b/web/src/components/config_render/ConfigGroup.jsx index 534d97cae4..15ce091579 100644 --- a/web/src/components/config_render/ConfigGroup.jsx +++ b/web/src/components/config_render/ConfigGroup.jsx @@ -13,6 +13,7 @@ import ConfigFileInput from "./ConfigFileInput"; import { setOrder } from "./ConfigUtil"; import { ConfigWrapper } from "./ConfigComponents"; import Icon from "../Icon"; +import ConfigDropdown from "./ConfigDropdown"; const ConfigGroup = (props) => { const markdownNode = createRef(); @@ -150,6 +151,19 @@ const ConfigGroup = (props) => { /> ); + case "radio": + return ( +