Make initial group config flow step a menu (#68565)
This commit is contained in:
parent
d3809e4a09
commit
a50bac5cc2
11 changed files with 164 additions and 91 deletions
|
@ -18,6 +18,7 @@ from homeassistant.const import (
|
||||||
from homeassistant.helpers import selector
|
from homeassistant.helpers import selector
|
||||||
from homeassistant.helpers.helper_config_entry_flow import (
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
HelperConfigFlowHandler,
|
HelperConfigFlowHandler,
|
||||||
|
HelperFlowMenuStep,
|
||||||
HelperFlowStep,
|
HelperFlowStep,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,9 +78,13 @@ CONFIG_SCHEMA = vol.Schema(
|
||||||
}
|
}
|
||||||
).extend(OPTIONS_SCHEMA.schema)
|
).extend(OPTIONS_SCHEMA.schema)
|
||||||
|
|
||||||
CONFIG_FLOW = {"user": HelperFlowStep(CONFIG_SCHEMA)}
|
CONFIG_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"user": HelperFlowStep(CONFIG_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
OPTIONS_FLOW = {"init": HelperFlowStep(OPTIONS_SCHEMA)}
|
OPTIONS_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"init": HelperFlowStep(OPTIONS_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Config flow for Group integration."""
|
"""Config flow for Group integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Mapping
|
from collections.abc import Callable, Mapping
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -11,6 +11,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import entity_registry as er, selector
|
from homeassistant.helpers import entity_registry as er, selector
|
||||||
from homeassistant.helpers.helper_config_entry_flow import (
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
HelperConfigFlowHandler,
|
HelperConfigFlowHandler,
|
||||||
|
HelperFlowMenuStep,
|
||||||
HelperFlowStep,
|
HelperFlowStep,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,43 +62,44 @@ LIGHT_CONFIG_SCHEMA = vol.Schema(
|
||||||
).extend(LIGHT_OPTIONS_SCHEMA.schema)
|
).extend(LIGHT_OPTIONS_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
INITIAL_STEP_SCHEMA = vol.Schema(
|
GROUP_TYPES = ["binary_sensor", "cover", "fan", "light", "media_player"]
|
||||||
{
|
|
||||||
vol.Required("group_type"): selector.selector(
|
|
||||||
{
|
|
||||||
"select": {
|
|
||||||
"options": [
|
|
||||||
"binary_sensor",
|
|
||||||
"cover",
|
|
||||||
"fan",
|
|
||||||
"light",
|
|
||||||
"media_player",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def choose_config_step(options: dict[str, Any]) -> str:
|
def choose_options_step(options: dict[str, Any]) -> str:
|
||||||
"""Return next step_id when group_type is selected."""
|
"""Return next step_id for options flow according to group_type."""
|
||||||
return cast(str, options["group_type"])
|
return cast(str, options["group_type"])
|
||||||
|
|
||||||
|
|
||||||
CONFIG_FLOW = {
|
def set_group_type(group_type: str) -> Callable[[dict[str, Any]], dict[str, Any]]:
|
||||||
"user": HelperFlowStep(INITIAL_STEP_SCHEMA, next_step=choose_config_step),
|
"""Set group type."""
|
||||||
"binary_sensor": HelperFlowStep(BINARY_SENSOR_CONFIG_SCHEMA),
|
|
||||||
"cover": HelperFlowStep(basic_group_config_schema("cover")),
|
@callback
|
||||||
"fan": HelperFlowStep(basic_group_config_schema("fan")),
|
def _set_group_type(user_input: dict[str, Any]) -> dict[str, Any]:
|
||||||
"light": HelperFlowStep(LIGHT_CONFIG_SCHEMA),
|
"""Add group type to user input."""
|
||||||
"media_player": HelperFlowStep(basic_group_config_schema("media_player")),
|
return {"group_type": group_type, **user_input}
|
||||||
|
|
||||||
|
return _set_group_type
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"user": HelperFlowMenuStep(GROUP_TYPES),
|
||||||
|
"binary_sensor": HelperFlowStep(
|
||||||
|
BINARY_SENSOR_CONFIG_SCHEMA, set_group_type("binary_sensor")
|
||||||
|
),
|
||||||
|
"cover": HelperFlowStep(
|
||||||
|
basic_group_config_schema("cover"), set_group_type("cover")
|
||||||
|
),
|
||||||
|
"fan": HelperFlowStep(basic_group_config_schema("fan"), set_group_type("fan")),
|
||||||
|
"light": HelperFlowStep(LIGHT_CONFIG_SCHEMA, set_group_type("light")),
|
||||||
|
"media_player": HelperFlowStep(
|
||||||
|
basic_group_config_schema("media_player"), set_group_type("media_player")
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OPTIONS_FLOW = {
|
OPTIONS_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
"init": HelperFlowStep(None, next_step=choose_config_step),
|
"init": HelperFlowStep(None, next_step=choose_options_step),
|
||||||
"binary_sensor": HelperFlowStep(BINARY_SENSOR_OPTIONS_SCHEMA),
|
"binary_sensor": HelperFlowStep(BINARY_SENSOR_OPTIONS_SCHEMA),
|
||||||
"cover": HelperFlowStep(basic_group_options_schema("cover")),
|
"cover": HelperFlowStep(basic_group_options_schema("cover")),
|
||||||
"fan": HelperFlowStep(basic_group_options_schema("fan")),
|
"fan": HelperFlowStep(basic_group_options_schema("fan")),
|
||||||
|
|
|
@ -4,8 +4,13 @@
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"title": "New Group",
|
"title": "New Group",
|
||||||
"data": {
|
"description": "Select group type",
|
||||||
"group_type": "Group type"
|
"menu_options": {
|
||||||
|
"binary_sensor": "Binary sensor group",
|
||||||
|
"cover": "Cover group",
|
||||||
|
"fan": "Fan group",
|
||||||
|
"light": "Light group",
|
||||||
|
"media_player": "Media player group"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"binary_sensor": {
|
"binary_sensor": {
|
||||||
|
|
|
@ -46,8 +46,13 @@
|
||||||
"title": "New Group"
|
"title": "New Group"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"description": "Select group type",
|
||||||
"group_type": "Group type"
|
"menu_options": {
|
||||||
|
"binary_sensor": "Binary sensor group",
|
||||||
|
"cover": "Cover group",
|
||||||
|
"fan": "Fan group",
|
||||||
|
"light": "Light group",
|
||||||
|
"media_player": "Media player group"
|
||||||
},
|
},
|
||||||
"title": "New Group"
|
"title": "New Group"
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ from homeassistant.const import (
|
||||||
from homeassistant.helpers import selector
|
from homeassistant.helpers import selector
|
||||||
from homeassistant.helpers.helper_config_entry_flow import (
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
HelperConfigFlowHandler,
|
HelperConfigFlowHandler,
|
||||||
|
HelperFlowMenuStep,
|
||||||
HelperFlowStep,
|
HelperFlowStep,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -87,9 +88,13 @@ CONFIG_SCHEMA = vol.Schema(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
CONFIG_FLOW = {"user": HelperFlowStep(CONFIG_SCHEMA)}
|
CONFIG_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"user": HelperFlowStep(CONFIG_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
OPTIONS_FLOW = {"init": HelperFlowStep(OPTIONS_SCHEMA)}
|
OPTIONS_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"init": HelperFlowStep(OPTIONS_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
||||||
|
|
|
@ -7,16 +7,18 @@ from typing import Any
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import CONF_ENTITY_ID, Platform
|
from homeassistant.const import CONF_ENTITY_ID, Platform
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import entity_registry as er, selector
|
||||||
entity_registry as er,
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
helper_config_entry_flow,
|
HelperConfigFlowHandler,
|
||||||
selector,
|
HelperFlowMenuStep,
|
||||||
|
HelperFlowStep,
|
||||||
|
wrapped_entity_config_entry_title,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .const import CONF_TARGET_DOMAIN, DOMAIN
|
from .const import CONF_TARGET_DOMAIN, DOMAIN
|
||||||
|
|
||||||
CONFIG_FLOW = {
|
CONFIG_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
"user": helper_config_entry_flow.HelperFlowStep(
|
"user": HelperFlowStep(
|
||||||
vol.Schema(
|
vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_ENTITY_ID): selector.selector(
|
vol.Required(CONF_ENTITY_ID): selector.selector(
|
||||||
|
@ -41,9 +43,7 @@ CONFIG_FLOW = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SwitchAsXConfigFlowHandler(
|
class SwitchAsXConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
||||||
helper_config_entry_flow.HelperConfigFlowHandler, domain=DOMAIN
|
|
||||||
):
|
|
||||||
"""Handle a config flow for Switch as X."""
|
"""Handle a config flow for Switch as X."""
|
||||||
|
|
||||||
config_flow = CONFIG_FLOW
|
config_flow = CONFIG_FLOW
|
||||||
|
@ -58,6 +58,4 @@ class SwitchAsXConfigFlowHandler(
|
||||||
options[CONF_ENTITY_ID], hidden_by=er.RegistryEntryHider.INTEGRATION
|
options[CONF_ENTITY_ID], hidden_by=er.RegistryEntryHider.INTEGRATION
|
||||||
)
|
)
|
||||||
|
|
||||||
return helper_config_entry_flow.wrapped_entity_config_entry_title(
|
return wrapped_entity_config_entry_title(self.hass, options[CONF_ENTITY_ID])
|
||||||
self.hass, options[CONF_ENTITY_ID]
|
|
||||||
)
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ from homeassistant.helpers import selector
|
||||||
from homeassistant.helpers.helper_config_entry_flow import (
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
HelperConfigFlowHandler,
|
HelperConfigFlowHandler,
|
||||||
HelperFlowError,
|
HelperFlowError,
|
||||||
|
HelperFlowMenuStep,
|
||||||
HelperFlowStep,
|
HelperFlowStep,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,11 +44,11 @@ CONFIG_SCHEMA = vol.Schema(
|
||||||
}
|
}
|
||||||
).extend(OPTIONS_SCHEMA.schema)
|
).extend(OPTIONS_SCHEMA.schema)
|
||||||
|
|
||||||
CONFIG_FLOW = {
|
CONFIG_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
"user": HelperFlowStep(CONFIG_SCHEMA, validate_user_input=_validate_mode)
|
"user": HelperFlowStep(CONFIG_SCHEMA, validate_user_input=_validate_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
OPTIONS_FLOW = {
|
OPTIONS_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
"init": HelperFlowStep(OPTIONS_SCHEMA, validate_user_input=_validate_mode)
|
"init": HelperFlowStep(OPTIONS_SCHEMA, validate_user_input=_validate_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ class FlowResult(TypedDict, total=False):
|
||||||
result: Any
|
result: Any
|
||||||
last_step: bool | None
|
last_step: bool | None
|
||||||
options: Mapping[str, Any]
|
options: Mapping[str, Any]
|
||||||
menu_options: list[str] | Mapping[str, Any]
|
menu_options: list[str] | dict[str, str]
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
|
|
@ -5,7 +5,8 @@ from abc import abstractmethod
|
||||||
from collections.abc import Callable, Mapping
|
from collections.abc import Callable, Mapping
|
||||||
import copy
|
import copy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
import types
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
@ -42,13 +43,21 @@ class HelperFlowStep:
|
||||||
next_step: Callable[[dict[str, Any]], str | None] = lambda _: None
|
next_step: Callable[[dict[str, Any]], str | None] = lambda _: None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class HelperFlowMenuStep:
|
||||||
|
"""Define a helper config or options flow menu step."""
|
||||||
|
|
||||||
|
# Menu options
|
||||||
|
options: list[str] | dict[str, str]
|
||||||
|
|
||||||
|
|
||||||
class HelperCommonFlowHandler:
|
class HelperCommonFlowHandler:
|
||||||
"""Handle a config or options flow for helper."""
|
"""Handle a config or options flow for helper."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
handler: HelperConfigFlowHandler | HelperOptionsFlowHandler,
|
handler: HelperConfigFlowHandler | HelperOptionsFlowHandler,
|
||||||
flow: dict[str, HelperFlowStep],
|
flow: dict[str, HelperFlowStep | HelperFlowMenuStep],
|
||||||
config_entry: config_entries.ConfigEntry | None,
|
config_entry: config_entries.ConfigEntry | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a common handler."""
|
"""Initialize a common handler."""
|
||||||
|
@ -60,24 +69,31 @@ class HelperCommonFlowHandler:
|
||||||
self, step_id: str, user_input: dict[str, Any] | None = None
|
self, step_id: str, user_input: dict[str, Any] | None = None
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Handle a step."""
|
"""Handle a step."""
|
||||||
next_step_id: str = step_id
|
if isinstance(self._flow[step_id], HelperFlowStep):
|
||||||
|
return await self._async_form_step(step_id, user_input)
|
||||||
|
return await self._async_menu_step(step_id, user_input)
|
||||||
|
|
||||||
if user_input is not None and self._flow[next_step_id].schema is not None:
|
async def _async_form_step(
|
||||||
|
self, step_id: str, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle a form step."""
|
||||||
|
form_step: HelperFlowStep = cast(HelperFlowStep, self._flow[step_id])
|
||||||
|
|
||||||
|
if user_input is not None and form_step.schema is not None:
|
||||||
# Do extra validation of user input
|
# Do extra validation of user input
|
||||||
try:
|
try:
|
||||||
user_input = self._flow[next_step_id].validate_user_input(user_input)
|
user_input = form_step.validate_user_input(user_input)
|
||||||
except HelperFlowError as exc:
|
except HelperFlowError as exc:
|
||||||
return self._show_next_step(next_step_id, exc, user_input)
|
return self._show_next_step(step_id, exc, user_input)
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
# User input was validated successfully, update options
|
# User input was validated successfully, update options
|
||||||
self._options.update(user_input)
|
self._options.update(user_input)
|
||||||
|
|
||||||
if self._flow[next_step_id].next_step and (
|
next_step_id: str = step_id
|
||||||
user_input is not None or self._flow[next_step_id].schema is None
|
if form_step.next_step and (user_input is not None or form_step.schema is None):
|
||||||
):
|
|
||||||
# Get next step
|
# Get next step
|
||||||
next_step_id_or_end_flow = self._flow[next_step_id].next_step(self._options)
|
next_step_id_or_end_flow = form_step.next_step(self._options)
|
||||||
if next_step_id_or_end_flow is None:
|
if next_step_id_or_end_flow is None:
|
||||||
# Flow done, create entry or update config entry options
|
# Flow done, create entry or update config entry options
|
||||||
return self._handler.async_create_entry(data=self._options)
|
return self._handler.async_create_entry(data=self._options)
|
||||||
|
@ -92,11 +108,13 @@ class HelperCommonFlowHandler:
|
||||||
error: HelperFlowError | None = None,
|
error: HelperFlowError | None = None,
|
||||||
user_input: dict[str, Any] | None = None,
|
user_input: dict[str, Any] | None = None,
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Show step for next step."""
|
"""Show form for next step."""
|
||||||
|
form_step: HelperFlowStep = cast(HelperFlowStep, self._flow[next_step_id])
|
||||||
|
|
||||||
options = dict(self._options)
|
options = dict(self._options)
|
||||||
if user_input:
|
if user_input:
|
||||||
options.update(user_input)
|
options.update(user_input)
|
||||||
if (data_schema := self._flow[next_step_id].schema) and data_schema.schema:
|
if (data_schema := form_step.schema) and data_schema.schema:
|
||||||
# Make a copy of the schema with suggested values set to saved options
|
# Make a copy of the schema with suggested values set to saved options
|
||||||
schema = {}
|
schema = {}
|
||||||
for key, val in data_schema.schema.items():
|
for key, val in data_schema.schema.items():
|
||||||
|
@ -115,12 +133,22 @@ class HelperCommonFlowHandler:
|
||||||
step_id=next_step_id, data_schema=data_schema, errors=errors
|
step_id=next_step_id, data_schema=data_schema, errors=errors
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _async_menu_step(
|
||||||
|
self, step_id: str, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle a menu step."""
|
||||||
|
form_step: HelperFlowMenuStep = cast(HelperFlowMenuStep, self._flow[step_id])
|
||||||
|
return self._handler.async_show_menu(
|
||||||
|
step_id=step_id,
|
||||||
|
menu_options=form_step.options,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HelperConfigFlowHandler(config_entries.ConfigFlow):
|
class HelperConfigFlowHandler(config_entries.ConfigFlow):
|
||||||
"""Handle a config flow for helper integrations."""
|
"""Handle a config flow for helper integrations."""
|
||||||
|
|
||||||
config_flow: dict[str, HelperFlowStep]
|
config_flow: dict[str, HelperFlowStep | HelperFlowMenuStep]
|
||||||
options_flow: dict[str, HelperFlowStep] | None = None
|
options_flow: dict[str, HelperFlowStep | HelperFlowMenuStep] | None = None
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
|
|
||||||
|
@ -146,7 +174,7 @@ class HelperConfigFlowHandler(config_entries.ConfigFlow):
|
||||||
|
|
||||||
# Create flow step methods for each step defined in the flow schema
|
# Create flow step methods for each step defined in the flow schema
|
||||||
for step in cls.config_flow:
|
for step in cls.config_flow:
|
||||||
setattr(cls, f"async_step_{step}", cls._async_step)
|
setattr(cls, f"async_step_{step}", cls._async_step(step))
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""Initialize config flow."""
|
"""Initialize config flow."""
|
||||||
|
@ -160,12 +188,19 @@ class HelperConfigFlowHandler(config_entries.ConfigFlow):
|
||||||
"""Return options flow support for this handler."""
|
"""Return options flow support for this handler."""
|
||||||
return cls.options_flow is not None
|
return cls.options_flow is not None
|
||||||
|
|
||||||
async def _async_step(self, user_input: dict[str, Any] | None = None) -> FlowResult:
|
@staticmethod
|
||||||
"""Handle a config flow step."""
|
def _async_step(step_id: str) -> Callable:
|
||||||
step_id = self.cur_step["step_id"] if self.cur_step else "user"
|
"""Generate a step handler."""
|
||||||
result = await self._common_handler.async_step(step_id, user_input)
|
|
||||||
|
|
||||||
return result
|
async def _async_step(
|
||||||
|
self: HelperConfigFlowHandler, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle a config flow step."""
|
||||||
|
# pylint: disable-next=protected-access
|
||||||
|
result = await self._common_handler.async_step(step_id, user_input)
|
||||||
|
return result
|
||||||
|
|
||||||
|
return _async_step
|
||||||
|
|
||||||
# pylint: disable-next=no-self-use
|
# pylint: disable-next=no-self-use
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -224,13 +259,25 @@ class HelperOptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
self._async_options_flow_finished = async_options_flow_finished
|
self._async_options_flow_finished = async_options_flow_finished
|
||||||
|
|
||||||
for step in options_flow:
|
for step in options_flow:
|
||||||
setattr(self, f"async_step_{step}", self._async_step)
|
setattr(
|
||||||
|
self,
|
||||||
|
f"async_step_{step}",
|
||||||
|
types.MethodType(self._async_step(step), self),
|
||||||
|
)
|
||||||
|
|
||||||
async def _async_step(self, user_input: dict[str, Any] | None = None) -> FlowResult:
|
@staticmethod
|
||||||
"""Handle an options flow step."""
|
def _async_step(step_id: str) -> Callable:
|
||||||
# pylint: disable-next=unsubscriptable-object # self.cur_step is a dict
|
"""Generate a step handler."""
|
||||||
step_id = self.cur_step["step_id"] if self.cur_step else "init"
|
|
||||||
return await self._common_handler.async_step(step_id, user_input)
|
async def _async_step(
|
||||||
|
self: HelperConfigFlowHandler, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle an options flow step."""
|
||||||
|
# pylint: disable-next=protected-access
|
||||||
|
result = await self._common_handler.async_step(step_id, user_input)
|
||||||
|
return result
|
||||||
|
|
||||||
|
return _async_step
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_create_entry( # pylint: disable=arguments-differ
|
def async_create_entry( # pylint: disable=arguments-differ
|
||||||
|
|
|
@ -10,6 +10,7 @@ from homeassistant.const import CONF_ENTITY_ID
|
||||||
from homeassistant.helpers import selector
|
from homeassistant.helpers import selector
|
||||||
from homeassistant.helpers.helper_config_entry_flow import (
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
HelperConfigFlowHandler,
|
HelperConfigFlowHandler,
|
||||||
|
HelperFlowMenuStep,
|
||||||
HelperFlowStep,
|
HelperFlowStep,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,9 +30,13 @@ CONFIG_SCHEMA = vol.Schema(
|
||||||
}
|
}
|
||||||
).extend(OPTIONS_SCHEMA.schema)
|
).extend(OPTIONS_SCHEMA.schema)
|
||||||
|
|
||||||
CONFIG_FLOW = {"user": HelperFlowStep(CONFIG_SCHEMA)}
|
CONFIG_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"user": HelperFlowStep(CONFIG_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
OPTIONS_FLOW = {"init": HelperFlowStep(OPTIONS_SCHEMA)}
|
OPTIONS_FLOW: dict[str, HelperFlowStep | HelperFlowMenuStep] = {
|
||||||
|
"init": HelperFlowStep(OPTIONS_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
||||||
|
|
|
@ -6,7 +6,11 @@ import pytest
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.group import DOMAIN, async_setup_entry
|
from homeassistant.components.group import DOMAIN, async_setup_entry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_FORM
|
from homeassistant.data_entry_flow import (
|
||||||
|
RESULT_TYPE_CREATE_ENTRY,
|
||||||
|
RESULT_TYPE_FORM,
|
||||||
|
RESULT_TYPE_MENU,
|
||||||
|
)
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
@ -42,12 +46,11 @@ async def test_config_flow(
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
)
|
)
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_MENU
|
||||||
assert result["errors"] is None
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{"group_type": group_type},
|
{"next_step_id": group_type},
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_FORM
|
||||||
|
@ -130,12 +133,11 @@ async def test_config_flow_hides_members(
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
)
|
)
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_MENU
|
||||||
assert result["errors"] is None
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{"group_type": group_type},
|
{"next_step_id": group_type},
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_FORM
|
||||||
|
@ -251,13 +253,11 @@ async def test_options(
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
)
|
)
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_MENU
|
||||||
assert result["errors"] is None
|
|
||||||
assert get_suggested(result["data_schema"].schema, "group_type") is None
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{"group_type": group_type},
|
{"next_step_id": group_type},
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert result["type"] == RESULT_TYPE_FORM
|
assert result["type"] == RESULT_TYPE_FORM
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue