Allow integrations to register custom config panels (#96245)

pull/97173/head
Franck Nijhof 2023-07-18 11:35:44 +02:00 committed by GitHub
parent a69b5a8d3b
commit 1a9e27cdaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 1 deletions

View File

@ -222,6 +222,9 @@ class Panel:
# If the panel should only be visible to admins
require_admin = False
# If the panel is a configuration panel for a integration
config_panel_domain: str | None = None
def __init__(
self,
component_name: str,
@ -230,6 +233,7 @@ class Panel:
frontend_url_path: str | None,
config: dict[str, Any] | None,
require_admin: bool,
config_panel_domain: str | None,
) -> None:
"""Initialize a built-in panel."""
self.component_name = component_name
@ -238,6 +242,7 @@ class Panel:
self.frontend_url_path = frontend_url_path or component_name
self.config = config
self.require_admin = require_admin
self.config_panel_domain = config_panel_domain
@callback
def to_response(self) -> PanelRespons:
@ -249,6 +254,7 @@ class Panel:
"config": self.config,
"url_path": self.frontend_url_path,
"require_admin": self.require_admin,
"config_panel_domain": self.config_panel_domain,
}
@ -264,6 +270,7 @@ def async_register_built_in_panel(
require_admin: bool = False,
*,
update: bool = False,
config_panel_domain: str | None = None,
) -> None:
"""Register a built-in panel."""
panel = Panel(
@ -273,6 +280,7 @@ def async_register_built_in_panel(
frontend_url_path,
config,
require_admin,
config_panel_domain,
)
panels = hass.data.setdefault(DATA_PANELS, {})
@ -720,3 +728,4 @@ class PanelRespons(TypedDict):
config: dict[str, Any] | None
url_path: str | None
require_admin: bool
config_panel_domain: str | None

View File

@ -92,6 +92,8 @@ async def async_register_panel(
config: ConfigType | None = None,
# If your panel should only be shown to admin users
require_admin: bool = False,
# If your panel is used to configure an integration, needs the domain of the integration
config_panel_domain: str | None = None,
) -> None:
"""Register a new custom panel."""
if js_url is None and module_url is None:
@ -127,6 +129,7 @@ async def async_register_panel(
frontend_url_path=frontend_url_path,
config=config,
require_admin=require_admin,
config_panel_domain=config_panel_domain,
)

View File

@ -265,6 +265,7 @@ async def test_setup_api_panel(
"title": None,
"url_path": "hassio",
"require_admin": True,
"config_panel_domain": None,
"config": {
"_panel_custom": {
"embed_iframe": True,

View File

@ -2,7 +2,7 @@
from unittest.mock import Mock, patch
from homeassistant import setup
from homeassistant.components import frontend
from homeassistant.components import frontend, panel_custom
from homeassistant.core import HomeAssistant
@ -155,3 +155,37 @@ async def test_url_path_conflict(hass: HomeAssistant) -> None:
]
},
)
async def test_register_config_panel(hass: HomeAssistant) -> None:
"""Test setting up a custom config panel for an integration."""
result = await setup.async_setup_component(hass, "panel_custom", {})
assert result
# Register a custom panel
await panel_custom.async_register_panel(
hass=hass,
frontend_url_path="config_panel",
webcomponent_name="custom-frontend",
module_url="custom-frontend",
embed_iframe=True,
require_admin=True,
config_panel_domain="test",
)
panels = hass.data.get(frontend.DATA_PANELS, [])
assert panels
assert "config_panel" in panels
panel = panels["config_panel"]
assert panel.config == {
"_panel_custom": {
"module_url": "custom-frontend",
"name": "custom-frontend",
"embed_iframe": True,
"trust_external": False,
},
}
assert panel.frontend_url_path == "config_panel"
assert panel.config_panel_domain == "test"

View File

@ -54,6 +54,7 @@ async def test_correct_config(hass: HomeAssistant) -> None:
assert panels.get("router").to_response() == {
"component_name": "iframe",
"config": {"url": "http://192.168.1.1"},
"config_panel_domain": None,
"icon": "mdi:network-wireless",
"title": "Router",
"url_path": "router",
@ -63,6 +64,7 @@ async def test_correct_config(hass: HomeAssistant) -> None:
assert panels.get("weather").to_response() == {
"component_name": "iframe",
"config": {"url": "https://www.wunderground.com/us/ca/san-diego"},
"config_panel_domain": None,
"icon": "mdi:weather",
"title": "Weather",
"url_path": "weather",
@ -72,6 +74,7 @@ async def test_correct_config(hass: HomeAssistant) -> None:
assert panels.get("api").to_response() == {
"component_name": "iframe",
"config": {"url": "/api"},
"config_panel_domain": None,
"icon": "mdi:weather",
"title": "Api",
"url_path": "api",
@ -81,6 +84,7 @@ async def test_correct_config(hass: HomeAssistant) -> None:
assert panels.get("ftp").to_response() == {
"component_name": "iframe",
"config": {"url": "ftp://some/ftp"},
"config_panel_domain": None,
"icon": "mdi:weather",
"title": "FTP",
"url_path": "ftp",